﻿/*
Copyright 2013 José A. Rojo L.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

/*
 * REFS:
 * http://blogs.msdn.com/b/shawnfa/archive/2006/10/09/the-differences-between-rijndael-and-aes.aspx
 * http://stackoverflow.com/questions/17171893/algorithm-is-the-rijndaelmanaged-class-in-c-sharp-equivalent-to-aes-encryption
 * https://cketkar.wordpress.com/2013/05/13/fips-compliance-aes-and-net-crypto/
 * http://blogs.msdn.com/b/shawnfa/archive/2004/04/14/113514.aspx
 * http://security.stackexchange.com/questions/52665/which-is-the-best-cipher-mode-and-padding-mode-for-aes-encryption
 * http://msdn.microsoft.com/en-us/library/system.security.cryptography.paddingmode.aspx
 * http://en.wikipedia.org/wiki/Padding_(cryptography)
 * https://msdn.microsoft.com/en-us/library/system.security.cryptography.symmetricalgorithm.legalkeysizes.aspx
 * https://msdn.microsoft.com/en-us/library/system.security.cryptography.symmetricalgorithm.iv(v=vs.110).aspx
 * https://msdn.microsoft.com/es-es/library/windows/desktop/aa386986(v=vs.85).aspx
 * http://stackoverflow.com/questions/7444586/how-can-i-sign-a-file-using-rsa-and-sha256-with-net
 * http://blog.aggregatedintelligence.com/2010/02/encryptingdecrypting-using.html
 * http://www.bouncycastle.org/csharp/
 * https://sites.google.com/site/lcastelli/cryptolib
 * https://hashlib.codeplex.com/
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.IO;
using System.Reflection;
using System.Diagnostics;
using System.Xml.Serialization;
using System.Runtime.InteropServices;

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Anssi;
using Org.BouncyCastle.Asn1.CryptoPro;
using Org.BouncyCastle.Asn1.TeleTrust;
using Org.BouncyCastle.Asn1.Nist;
using Org.BouncyCastle.Asn1.Sec;
using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Bcpg;
using Org.BouncyCastle.Bcpg.OpenPgp;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.EC;
using Org.BouncyCastle.Crypto.Agreement;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Macs;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Math.EC.Custom.Sec;
using Org.BouncyCastle.Security;

using CryptoLib.SymmetricAlgorithms;                                                                    // MARS

using HashLib;                                                                                          // HASHES
using HashLib.Crypto;
using HashLib.Crypto.SHA3;
using HashLib.Hash32;
using HashLib.Hash64;
using HashLib.Hash128;
using HashLib.Checksum;

using Jarol.Console;
using Jarol.IO;

namespace crypter
{
    public class Program
    {   
        private enum CryptOperation
        {
              NONE
            , ENCRYPT
            , DECRYPT
        };

        private enum CryptFormat
        {
              BLOB
            , XML
            , ARMORED
            , UNKNOWN
        };

        private enum CryptPadding
        {
              PKCS7     = 2
            , Zeros     = 3
            , ANSIX923  = 4
            , ISO10126  = 5
            , ISO7816   = 6
            , TBC       = 7
            , OAEP      = 8
            , PKCS1     = 9
            , ISO9796D1 = 10
        };

        //----------------------------------------------------------------------------------

        private struct SymmetricKey
        {
            public byte[] key;
            public byte[] iv;
        }

        //----------------------------------------------------------------------------------

        public struct ElGamalKey
        {
            public byte[] p;                                                                // Modulus. 
            public byte[] g;                                                                // Generator.
            public int    l;
            public byte[] n;                                                                // Public or private key (y or x respectively).
            public bool   b;                                                                // Public or private key signal.
        }

        //----------------------------------------------------------------------------------

        public struct NaccacheSternKey
        {
            public byte[]   g;
            public byte[]   n;                                                              // Modulus.
            public byte[]   p;                                                              // phiN.
            public int      l;                                                              // Lower Sigma Bound.
            public byte[][] s;                                                              // Small prime list.
            public bool     b;                                                              // Public or private key signal.
        }

        //----------------------------------------------------------------------------------

        public struct EciesKey
        {
            public byte[] c;
            public byte[] d;
            public byte[] n;
            public byte[] h;
            public byte[] s;
            public byte[] g;
            public byte[] q;
            public byte[] cq;
            public byte[] ca;
            public byte[] cb;
            public byte[] co;
            public byte[] ch;
            public int    cm;
            public int    ck1;
            public int    ck2;
            public int    ck3;
            public bool   b;                                                                // Public or private key signal.
        }

        //----------------------------------------------------------------------------------

        public struct DliesKey
        {
            public byte[] a;
            public byte[] x;
            public byte[] y;
            public byte[] g;
            public byte[] j;
            public byte[] p;
            public byte[] q;
            public byte[] s;
            public int    c;
            public int    l;
            public int    m;
            public bool   b;                                                                // Public or private key signal.
        }

        //----------------------------------------------------------------------------------

        private const string MSG_PROCESSING            = "Processing. Please wait...";
        private const string MSG_INVALID_OUTPUT        = "Invalid output file or directory!";
        private const string MSG_INVALID_KEY_SIZE      = "Invalid key size!";
        private const string MSG_INVALID_BLOCK_SIZE    = "Invalid block size!";
        private const string MSG_INVALID_FEEDBACK_SIZE = "Invalid feedback size!";
        private const string MSG_INVALID_PUBLIC_KEY    = "Invalid public key file name!";
        private const string MSG_INVALID_PRIVATE_KEY   = "Invalid private key file name!";
        private const string MSG_INVALID_KEY_PAIR      = "Invalid key pair!";
        private const string MSG_INVALID_CIPHER_MODE   = "Invalid cipher mode!";
        private const string MSG_INVALID_BUFFER_SIZE   = "Invalid buffer size!";
        private const string MSG_INVALID_PADDING_MODE  = "Invalid padding mode!";
        private const string MSG_INVALID_HASH          = "Invalid hash!";
        private const string MSG_INVALID_IV            = "The initial vector needs to be {0} characters length!";
        private const string MSG_INVALID_RADIX         = "Radix must be between 2 and 64!";
        private const string MSG_INVALID_CODE          = "Invalid length or repeated characters in the base code string!";
        private const string MSG_INVALID_BASE_SEQ      = "Invalid Base{0} sequence";
        private const string MSG_INVALID_IES_CIPHER    = "Invalid Ies cipher!";
        private const string MSG_INVALID_PGP_ALGORITHM = "Invalid Pgp algorithm!";
        private const string MSG_INVALID_CURVE_STORE   = "Invalid curve store!";
        private const string MSG_INVALID_HASH_KEY_SIZE = "Can't use the {0} hash, The key has a size less than {1}!";
        private const string MSG_INVALID_RSA_KEY       = "The key type is not Rsa!";
        private const string MSG_INVALID_ELGAMAL_KEY   = "The key type is not ElGamal!";
        private const string MSG_INVALID_EXPORT_PARAMS = "Invalid export parameters!";
        private const string MSG_IV_DOES_NOT_ALLOW     = "The current mode or operation does not allow initial vector and will not be processed!";
        private const string MSG_CER_ALG_INCOMPATIBLE  = "The use of certificates only is compatible with the RSA algorithm. Others are ignored!";
        private const string MSG_GEN_INCOMPATIBLE      = "The key pair generation can not be used simultaneously with certificates or decryption processes and will not be considered!";
        private const string MSG_CROSS_INCOMPATIBLE    = "The crossbreeding modifier can not be used simultaneously with key pair generation!";
        private const string MSG_FILE_WAS_NOT_FOUND    = "The file(s) was not found: \"{0}\"";
        private const string MSG_PROCESS_CANCELLED     = "Process cancelled by user!\n";
        private const string MSG_DONE                  = "Done!\n";
        private const string MSG_PASSWORD              = "You must enter at least 1 character.\n\n> Password: ";
        private const string MSG_CONFIRM_PWD           = "Confirm the password. Enter the password again.\n\n> Password: ";
        private const string MSG_SALT                  = "You must enter at least 8 characters or nothing at all.\n\n> Salt: ";
        private const string MSG_PRIVATE_KEY_PWD       = "Private key password: ";
        private const string MSG_NO_PGP_KEY_FOUND      = "No Pgp {0} key found!";
        private const string MSG_WRONG_LINE_WRAP       = "Wrong line wrap for Base{0} encode!";
        private const string MSG_CONTINUE_QUESTION     = "\n\n> Do you want to continue?";
        private const string MSG_EXPORT_PWD_QUESTION   = "Do you want to use the certificate password for Pgp private key?";
        private const string MSG_EXCEPTION_LOOPING     = "The same exception has produced more than {0} consecutive times!";
        private const string MSG_INCORRECT_PASSWORD    = "Incorrect password! ";
        private const string MSG_INCORRECT_PWD_SALT    = "Incorrect password or salt";
        private const string MSG_PLEASE_TRY_AGAIN      = "Please try again!";
        private const string MSG_KEYPAIR_INSECURE      = "The resulting key pair might not be secure!";
        private const string MSG_LARGE_KEYSIZE         = "The key size is considerably large, It will take a long time!";
        private const string MSG_MALFORMED_CMD_LINE    = "Malformed command line!";
        private const string MSG_PUBLIC_KEY_ONLY       = "There is only one public key!";
        private const string MSG_EXPORT_USE            = "The export modifier can not be used simultaneously with encryption, decryption, or key pair generation!";
        private const string MSG_PGP_SIGN_USE          = "The signature parameter is not necessary for decryption, exportation, or key pair generation and will not be processed!";
        private const string MSG_GENERIC_USE           = "The {0} parameter is not necessary or supported for current mode or operation and will not be processed!";
        private const string MSG_UNICODE_QUESTION      = "The string contains Unicode characters!\n\n> Do you want to keep them?";
        private const string MSG_UNICODE_CHANGE        = "The character encoding was changed to Unicode!";
        private const string FILES                     = " files.";
        private const string HASH_BLAKE224             = "BLAKE224";
        private const string HASH_BLAKE256             = "BLAKE256";
        private const string HASH_BLAKE384             = "BLAKE384";
        private const string HASH_BLAKE512             = "BLAKE512";
        private const string HASH_BMW224               = "BMW224";
        private const string HASH_BMW256               = "BMW256";
        private const string HASH_BMW384               = "BMW384";
        private const string HASH_BMW512               = "BMW512";
        private const string HASH_CUBE224              = "CUBE224";
        private const string HASH_CUBE256              = "CUBE256";
        private const string HASH_CUBE384              = "CUBE384";
        private const string HASH_CUBE512              = "CUBE512";
        private const string HASH_ECHO224              = "ECHO224";
        private const string HASH_ECHO256              = "ECHO256";
        private const string HASH_ECHO384              = "ECHO384";
        private const string HASH_ECHO512              = "ECHO512";
        private const string HASH_FUGUE224             = "FUGUE224";
        private const string HASH_FUGUE256             = "FUGUE256";
        private const string HASH_FUGUE384             = "FUGUE384";
        private const string HASH_FUGUE512             = "FUGUE512";
        private const string HASH_GROESTL224           = "GROESTL224";
        private const string HASH_GROESTL256           = "GROESTL256";
        private const string HASH_GROESTL384           = "GROESTL384";
        private const string HASH_GROESTL512           = "GROESTL512";
        private const string HASH_HAMSI224             = "HAMSI224";
        private const string HASH_HAMSI256             = "HAMSI256";
        private const string HASH_HAMSI384             = "HAMSI384";
        private const string HASH_HAMSI512             = "HAMSI512";
        private const string HASH_JH224                = "JH224";
        private const string HASH_JH256                = "JH256";
        private const string HASH_JH384                = "JH384";
        private const string HASH_JH512                = "JH512";
        private const string HASH_KECCAK224            = "KECCAK224";
        private const string HASH_KECCAK256            = "KECCAK256";
        private const string HASH_KECCAK384            = "KECCAK384";
        private const string HASH_KECCAK512            = "KECCAK512";
        private const string HASH_LUFFA224             = "LUFFA224";
        private const string HASH_LUFFA256             = "LUFFA256";
        private const string HASH_LUFFA384             = "LUFFA384";
        private const string HASH_LUFFA512             = "LUFFA512";
        private const string HASH_SHABAL224            = "SHABAL224";
        private const string HASH_SHABAL256            = "SHABAL256";
        private const string HASH_SHABAL384            = "SHABAL384";
        private const string HASH_SHABAL512            = "SHABAL512";
        private const string HASH_SHAVITE_224          = "SHAVITE224";
        private const string HASH_SHAVITE_256          = "SHAVITE256";
        private const string HASH_SHAVITE_384          = "SHAVITE384";
        private const string HASH_SHAVITE_512          = "SHAVITE512";
        private const string HASH_SIMD224              = "SIMD224";
        private const string HASH_SIMD256              = "SIMD256";
        private const string HASH_SIMD384              = "SIMD384";
        private const string HASH_SIMD512              = "SIMD512";
        private const string HASH_SKEIN224             = "SKEIN224";
        private const string HASH_SKEIN256             = "SKEIN256";
        private const string HASH_SKEIN384             = "SKEIN384";
        private const string HASH_SKEIN512             = "SKEIN512";
        private const string HASH_RIPEMD               = "RIPEMD";
        private const string HASH_RIPEMD128            = "RIPEMD128";
        private const string HASH_RIPEMD160            = "RIPEMD160";
        private const string HASH_RIPEMD256            = "RIPEMD256";
        private const string HASH_RIPEMD320            = "RIPEMD320";
        private const string HASH_SHA224               = "SHA224";
        private const string HASH_SHA256               = "SHA256";
        private const string HASH_SHA384               = "SHA384";
        private const string HASH_SHA512               = "SHA512";
        private const string HASH_SHA1                 = "SHA1";
        private const string HASH_SHA0                 = "SHA0";
        private const string HASH_MD4                  = "MD4";
        private const string HASH_MD2                  = "MD2";
        private const string HASH_MD5                  = "MD5";
        private const string HASH_GRINDAHL256          = "GRINDAHL256";
        private const string HASH_GRINDAHL512          = "GRINDAHL512";
        private const string HASH_HAS160               = "HAS160";
        private const string HASH_HAVAL3_128           = "HAVAL3-128";
        private const string HASH_HAVAL3_160           = "HAVAL3-160";
        private const string HASH_HAVAL3_192           = "HAVAL3-192";
        private const string HASH_HAVAL3_224           = "HAVAL3-224";
        private const string HASH_HAVAL3_256           = "HAVAL3-256";
        private const string HASH_HAVAL4_128           = "HAVAL4-128";
        private const string HASH_HAVAL4_160           = "HAVAL4-160";
        private const string HASH_HAVAL4_192           = "HAVAL4-192";
        private const string HASH_HAVAL4_224           = "HAVAL4-224";
        private const string HASH_HAVAL4_256           = "HAVAL4-256";
        private const string HASH_HAVAL5_128           = "HAVAL5-128";
        private const string HASH_HAVAL5_160           = "HAVAL5-160";
        private const string HASH_HAVAL5_192           = "HAVAL5-192";
        private const string HASH_HAVAL5_224           = "HAVAL5-224";
        private const string HASH_HAVAL5_256           = "HAVAL5-256";
        private const string HASH_PANAMA               = "PANAMA";
        private const string HASH_RG32                 = "RG32";
        private const string HASH_RG64                 = "RG64";
        private const string HASH_SNEFRU4_128          = "SNEFRU4-128";
        private const string HASH_SNEFRU4_256          = "SNEFRU4-256";
        private const string HASH_SNEFRU8_128          = "SNEFRU8-128";
        private const string HASH_SNEFRU8_256          = "SNEFRU8-256";
        private const string HASH_TIGER2               = "TIGER2";
        private const string HASH_TIGER3_192           = "TIGER3-192";
        private const string HASH_TIGER4_192           = "TIGER4-192";
        private const string HASH_WHIRLPOOL            = "WHIRLPOOL";
        private const string HASH_AP                   = "AP";
        private const string HASH_BERNSTEIN            = "BERNSTEIN";
        private const string HASH_BERNSTEIN1           = "BERNSTEIN1";
        private const string HASH_BKDR                 = "BKDR";
        private const string HASH_DEK                  = "DEK";
        private const string HASH_DJB                  = "DJB";
        private const string HASH_DOTNET               = "DOTNET";
        private const string HASH_ELF                  = "ELF";
        private const string HASH_FNV                  = "FNV";
        private const string HASH_FNV1A                = "FNV1A";
        private const string HASH_FNV64                = "FNV64";
        private const string HASH_FNV1A64              = "FNV1A64";
        private const string HASH_JENKINS3             = "JENKINS3";
        private const string HASH_JS                   = "JS";
        private const string HASH_MURMUR2              = "MURMUR2";
        private const string HASH_MURMUR2_64           = "MURMUR2-64";
        private const string HASH_MURMUR3              = "MURMUR3";
        private const string HASH_MURMUR3_128          = "MURMUR3-128";
        private const string HASH_ONEATTIME            = "ONEATTIME";
        private const string HASH_PJW                  = "PJW";
        private const string HASH_ROTATING             = "ROTATING";
        private const string HASH_RS                   = "RS";
        private const string HASH_SDBM                 = "SDBM";
        private const string HASH_SHIFTANDXOR          = "SNX";
        private const string HASH_SUPERFAST            = "SUPERFAST";
        private const string HASH_SIPHASH              = "SIPHASH";
        private const string HASH_ADLER32              = "ADLER32";
        private const string HASH_CRC32_IEEE           = "CRC32-IEEE";
        private const string HASH_CRC32_CASTAGNOLI     = "CRC32-CASTAGNOLI";
        private const string HASH_CRC32_KOOPMAN        = "CRC32-KOOPMAN";
        private const string HASH_CRC32_Q              = "CRC32-Q";
        private const string HASH_CRC64_ISO            = "CRC64-ISO";
        private const string HASH_CRC64_ECMA           = "CRC64-ECMA";
        private const string MOD_SHORT_MODE            = "-m";
        private const string MOD_LONG_MODE             = "--mode";
        private const string MOD_SHORT_HASH            = "-h";
        private const string MOD_LONG_HASH             = "--hash";
        private const string MOD_SHORT_KEY_SIZE        = "-y";
        private const string MOD_LONG_KEY_SIZE         = "--key-size";
        private const string MOD_SHORT_IO_OPTIONS      = "-7";
        private const string MOD_LONG_IO_OPTIONS       = "--io-options";
        private const string MOD_LONG_EXPORT           = "--export";
        private const string MOD_LONG_HELP             = "--help";
        private const string DIGEST                    = "DIGEST";
        private const string CHECKSUM                  = "CHECKSUM";
        private const string BIN                       = "BIN";
        private const string HEX                       = "HEX";
        private const string OCTAL                     = "OCTAL";
        private const string DECIMAL                   = "DECIMAL";
        private const string B2                        = "B2";
        private const string B3                        = "B3";
        private const string B4                        = "B4";
        private const string B5                        = "B5";
        private const string B6                        = "B6";
        private const string B7                        = "B7";
        private const string B8                        = "B8";
        private const string B9                        = "B9";
        private const string B10                       = "B10";
        private const string B11                       = "B11";
        private const string B12                       = "B12";
        private const string B13                       = "B13";
        private const string B14                       = "B14";
        private const string B15                       = "B15";
        private const string B16                       = "B16";
        private const string B17                       = "B17";
        private const string B18                       = "B18";
        private const string B19                       = "B19";
        private const string B20                       = "B20";
        private const string B21                       = "B21";
        private const string B22                       = "B22";
        private const string B23                       = "B23";
        private const string B24                       = "B24";
        private const string B25                       = "B25";
        private const string B26                       = "B26";
        private const string B27                       = "B27";
        private const string B28                       = "B28";
        private const string B29                       = "B29";
        private const string B30                       = "B30";
        private const string B31                       = "B31";
        private const string B32                       = "B32";
        private const string B33                       = "B33";
        private const string B34                       = "B34";
        private const string B35                       = "B35";
        private const string B36                       = "B36";
        private const string B37                       = "B37";
        private const string B38                       = "B38";
        private const string B39                       = "B39";
        private const string B40                       = "B40";
        private const string B41                       = "B41";
        private const string B42                       = "B42";
        private const string B43                       = "B43";
        private const string B44                       = "B44";
        private const string B45                       = "B45";
        private const string B46                       = "B46";
        private const string B47                       = "B47";
        private const string B48                       = "B48";
        private const string B49                       = "B49";
        private const string B50                       = "B50";
        private const string B51                       = "B51";
        private const string B52                       = "B52";
        private const string B53                       = "B53";
        private const string B54                       = "B54";
        private const string B55                       = "B55";
        private const string B56                       = "B56";
        private const string B57                       = "B57";
        private const string B58                       = "B58";
        private const string B59                       = "B59";
        private const string B60                       = "B60";
        private const string B61                       = "B61";
        private const string B62                       = "B62";
        private const string B63                       = "B63";
        private const string B64                       = "B64";
        private const string AES                       = "AES";
        private const string RIJNDAEL                  = "RIJNDAEL";
        private const string TDES                      = "3DES";
        private const string DES                       = "DES";
        private const string RC2                       = "RC2";
        private const string MARS                      = "MARS";
        private const string SALSA20                   = "SALSA20";
        private const string XSALSA20                  = "XSALSA20";
        private const string CHACHA                    = "CHACHA";
        private const string VMPC                      = "VMPC";
        private const string CAMELLIA                  = "CAMELLIA";
        private const string BLOWFISH                  = "BLOWFISH";
        private const string TWOFISH                   = "2FISH";
        private const string THREEFISH                 = "3FISH";
        private const string SERPENT                   = "SERPENT";
        private const string TNEPRES                   = "TNEPRES";
        private const string CAST5                     = "CAST5";
        private const string CAST6                     = "CAST6";
        private const string IDEA                      = "IDEA";
        private const string NOEKEON                   = "NOEKEON";
        private const string TEA                       = "TEA";
        private const string XTEA                      = "XTEA";
        private const string GOST                      = "GOST";
        private const string SEED                      = "SEED";
        private const string SKIPJACK                  = "SKIPJACK";
        private const string RC6                       = "RC6";
        private const string RC5                       = "RC5";
        private const string RC4                       = "RC4";
        private const string HC                        = "HC";
        private const string ISAAC                     = "ISAAC";
        private const string RSA                       = "RSA";
        private const string PGP                       = "PGP";
        private const string ELGAMAL                   = "ELGAMAL";
        private const string NACCACHE                  = "NACCACHE";
        private const string ECIES                     = "ECIES";
        private const string DLIES                     = "DLIES";
        private const string CUSTOM                    = "CUSTOM";
        private const string ANSSI                     = "ANSSI";
        private const string TELETRUST                 = "TELETRUST";
        private const string NIST                      = "NIST";
        private const string X962                      = "X962";
        private const string SEC                       = "SEC";
        private const string DSA                       = "DSA";
        private const string ECDSA                     = "ECDSA";
        private const string ECDH                      = "ECDH";
        private const string IV                        = "IV";
        private const string CODE                      = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/";
        private const string BASE32                    = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
        private const string BASE32HEX                 = "0123456789ABCDEFGHIJKLMNOPQRSTUV";
        private const string DEFCURVE                  = "sect571r1";
        private const string OUT                       = "output";
        private const string RANDOM                    = "random-gen";
        private const string RSA_BC                    = "rsa-bouncy-castle";

        //----------------------------------------------------------------------------------

        private static readonly char[] _io_options_separator = new char[] { ',' };
        private static readonly char[] _path_delimiter       = new char[] { ';' };
        
        //----------------------------------------------------------------------------------

        private static bool           _banner          = true;
        private static byte           _percent         = 100;
        private static int            _buffersize      = 1024;
        private static string         _password        = string.Empty;
        private static bool           _haspwd          = false;
        private static string         _salt            = string.Empty;
        private static bool           _saltleaking     = false;
        private static string         _hash            = HASH_SHA512;
        private static string         _key             = string.Empty;
        private static string         _iv              = string.Empty;
        private static bool           _without_iv      = false;
        private static bool           _rsa_bc          = false;
        private static short          _keysize         = -1;
        private static short          _blocksize       = -1;
        private static short          _feedbacksize    = -1;
        private static int            _iterations      = 1000;
        private static int            _rounds          = 20;
        private static CipherMode     _ciphermode      = CipherMode.CBC;
        private static CryptPadding   _padding         = CryptPadding.PKCS7;
        private static CryptFormat    _format          = CryptFormat.UNKNOWN;
        private static CryptOperation _cop             = CryptOperation.NONE;
        private static Finder         _finder          = null;
        private static Finder.Mode    _findermode      = Finder.Mode.Basic;
        private static bool           _ignorecase      = true;
        private static bool           _recursively     = false;
        private static bool           _reverse         = false;
        private static bool           _raise           = true;
        private static bool           _raisepwd        = false;
        private static bool           _b32hex          = false;
        private static bool           _rfc4648         = true;
        private static bool           _ksa3            = false;
        private static bool           _rc5b64          = false;
        private static bool           _unesc           = false;
        private static bool           _generator       = false;
        private static bool           _overwrite       = false;
        private static bool           _crossbreeding   = false;
        private static bool           _random          = false;
        private static bool           _sha1            = false;
        private static string         _public_key      = string.Empty;
        private static string         _private_key     = string.Empty;
        private static bool           _export          = false;
        private static string         _export_pbk      = string.Empty;
        private static string         _export_pvk      = string.Empty;
        private static string         _export_pwd      = string.Empty;
        private static string         _curve           = DEFCURVE;
        private static string         _curvestore      = SEC;
        private static string         _code            = CODE;
        private static short          _charsperline    = 0;
        private static string         _cer_pgp_pvk     = string.Empty;
        private static string         _cerfile         = string.Empty;
        private static string         _cerstore        = string.Empty;
        private static string         _pgp_algorithm   = RSA;
        private static string         _pgp_id          = string.Empty;
        private static string         _pgp_master      = string.Empty;
        private static bool           _pgp_sign        = false;
        private static PgpPrivateKey  _pgp_pvk         = null;
        private static string         _ies_cipher      = AES;
        private static SymmetricKey   _sk              = new SymmetricKey();
        private static bool           _tellapart       = false;
        private static byte           _e_cnt           = 0;
        private static int            _e_num           = 0;
        private static byte           _e_max           = 5;
        private static bool           _pathdelimiter   = true;
        private static bool           _hasprivatekey   = false;
        private static string         _sbox            = string.Empty;
        private static Encoding       _encoding        = Encoding.ASCII;

        private static SymmetricKeyAlgorithmTag _ska   = SymmetricKeyAlgorithmTag.Aes256;

        //----------------------------------------------------------------------------------

        private static string Prompt 
        (
              string msg
            , bool   hidden
            , short  minlen = 1
            , bool   empty  = false
        ){
            StringBuilder sb = new StringBuilder();
            Messenger.Print(Messenger.Icon.WARNING, msg);

            do
            {
                ConsoleKeyInfo ki = Console.ReadKey(true);

                if (ki.Key == ConsoleKey.Enter && ((empty && sb.Length == 0) || sb.Length >= minlen))
                    break;

                else if (ki.Key == ConsoleKey.Backspace)
                {
                    if (sb.Length > 0)
                    {
                        sb.Remove(sb.Length - 1, 1);
                        Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
                        Console.Write(' ');
                        Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
                    }
                }

                else if
                (
                    ((byte)ki.KeyChar > 31 && (byte)ki.KeyChar < 127) ||
                    ((byte)ki.KeyChar > 128)
                ){
                    sb.Append(ki.KeyChar);
                    Console.Write(hidden ? '*' : ki.KeyChar);
                }
            }
            while (true);

            if (msg.IndexOf('\n') != -1)
                Console.WriteLine();

            return sb.ToString();
        }

        //--------------------------------------------------------------------------------

        private static void Delay (long milliseconds)
        {
            Stopwatch w = Stopwatch.StartNew();
            while (w.ElapsedMilliseconds < milliseconds);
            w.Stop();
        }

        //--------------------------------------------------------------------------------

        private static void Progress (double current, double total, int block)
        {
            if (current == block)
                Console.Write('\n');

            _percent = (byte)Math.Floor(current / total * 100);
            block    = _percent / 10;

            StringBuilder s = new StringBuilder();

            s.Append("[");
            for (short i = 0; i < 11; ++i)
                s.Append(i <= block ? '#' : ' ');

            s.Append("]: ");
            s.Append(_percent);
            s.Append('%');

            Console.SetCursorPosition(0, Console.CursorTop);
            Console.Write(s);

            if (_percent == 100)
            {
                Program.Delay(500);
                Console.SetCursorPosition(0, Console.CursorTop);

                for (byte i = 0; i < 20; ++i)
                    Console.Write(' ');

                Console.SetCursorPosition(0, Console.CursorTop - 1);
            }
        }

        //--------------------------------------------------------------------------------

        private static void LineWrapper (Stream dest, long current, ref long total)
        {
            if (total > 0 && current > total)
            {
                dest.WriteByte(10);
                total += _charsperline;
            }
        }

        //--------------------------------------------------------------------------------

        private static void Write
        (
              ICryptoTransform ct
            , Stream           src
            , Stream           dest
            , bool             progressbar
        ){
            if (_charsperline > 0 && (_charsperline < 4 || _charsperline > 256 || _charsperline % 4 != 0))
                throw new Exception(string.Format(MSG_WRONG_LINE_WRAP, 64));

            byte[] o = new byte[ct.OutputBlockSize];
            byte[] i = new byte[ct.InputBlockSize];
            long   w = _charsperline - 1;
            long   l = src.Length;
            long   p = l - ct.InputBlockSize;
            long   c = 0;
            long   t = 0;
            int    n = 0;
            int    k = 0;

            while (c < p)
            {
                if ((n = src.Read(i, 0, i.Length)) > 0)
                {
                    Program.LineWrapper(dest, t, ref w);
                    dest.Write(o, 0, k = ct.TransformBlock(i, 0, n, o, 0));
                    
                    t += k;
                    c += n;

                    if (progressbar)
                        Program.Progress(c, l, n);
                }
            }

            if (c > 0)
            {
                Program.LineWrapper(dest, t, ref w);

                n = src.Read(i, 0, i.Length);
                Array.Clear(o, 0, o.Length);

                o = ct.TransformFinalBlock(i, 0, n);
                dest.Write(o, 0, o.Length);

                Array.Clear(o, 0, o.Length);
                Array.Clear(i, 0, i.Length);

                if (progressbar)
                    Program.Progress(c + n, l, n);
            }
        }
        
        //--------------------------------------------------------------------------------

        private static void Base64Encode (Stream src, Stream dest, bool progressbar = true)
        {
            using (ToBase64Transform t = new ToBase64Transform())
                Program.Write(t, src, dest, progressbar);
        }

        //--------------------------------------------------------------------------------

        private static byte[] Base64Encode (byte[] data, bool progressbar = false)
        {
            byte[] b = null;

            using (MemoryStream dt = new MemoryStream(data))
            {
                using (MemoryStream bf = new MemoryStream())
                {
                    Program.Base64Encode(dt, bf, progressbar);
                    b = bf.ToArray();
                }
            }

            return b;
        }

        //--------------------------------------------------------------------------------

        private static byte[] Base64Encode (string data, bool progressbar = false)
        {
            byte[] d = Encoding.ASCII.GetBytes(data);
            byte[] b = Program.Base64Encode(d, progressbar);

            Array.Clear(d, 0, d.Length);
            return b;
        }


        //--------------------------------------------------------------------------------

        private static void Base64Decode (Stream src, Stream dest, bool progressbar = true)
        {
            using (FromBase64Transform t = new FromBase64Transform(FromBase64TransformMode.IgnoreWhiteSpaces))
                Program.Write(t, src, dest, progressbar);
        }

        //--------------------------------------------------------------------------------

        private static byte[] Base64Decode (byte[] data, bool progressbar = false)
        {
            byte[] b = null;

            using (MemoryStream dt = new MemoryStream(data))
            {
                using (MemoryStream bf = new MemoryStream())
                {
                    Program.Base64Decode(dt, bf, progressbar);
                    b = bf.ToArray();
                }
            }

            return b;
        }

        //--------------------------------------------------------------------------------

        private static byte[] Base64Decode (string data, bool progressbar = false)
        {
            byte[] d = Encoding.ASCII.GetBytes(data);
            byte[] b = Program.Base64Decode(d, progressbar);

            Array.Clear(d, 0, d.Length);
            return b;
        }

        //--------------------------------------------------------------------------------

        public static void Base32Encode (Stream src, Stream dest)
        {
            if (_charsperline > 0 && (_charsperline < 2 || _charsperline > 256))
                throw new Exception(string.Format(MSG_WRONG_LINE_WRAP, 32));

            string s = _b32hex ? BASE32HEX : BASE32;
            long   l = src.Length;
            long   n = (long)Math.Ceiling((l / 5f)) * 8;
            long   w = _charsperline - 1;
            short  r = 5;
            long   c = 0;
            long   p = 0;
            byte   t = 0;
            int    b;

            while ((b = src.ReadByte()) > -1)
            {
                Program.LineWrapper(dest, c++, ref w);
                dest.WriteByte((byte)s[t | (b >> 8 - r)]);

                if (r <= 3)
                {
                    Program.LineWrapper(dest, c++, ref w);
                    dest.WriteByte((byte)s[(b >> 3 - r) & 31]);
                    r += 5;
                }

                t = (byte)((b << (r -= 3)) & 31);
                Program.Progress(++p, l, 1);
            }

            if (c != n)
            {
                Program.LineWrapper(dest, c++, ref w);
                dest.WriteByte((byte)s[t]);
            }

            while (c < n)
            {
                Program.LineWrapper(dest, c++, ref w);
                dest.WriteByte(61);
            }
        }

        //--------------------------------------------------------------------------------

        public static void Base32Decode (Stream src, Stream dest)
        {
            string e = string.Format(MSG_INVALID_BASE_SEQ + '!', 32);
            string s = _b32hex ? BASE32HEX : BASE32;
            long   c = 0;
            int    r = 8;
            int    t = 0;
            byte   p = 0;
            int    n, b;

            while ((b = src.ReadByte()) > -1)
            {
                Program.Progress(++c, src.Length, 1);

                if ((b > 6 && b < 14) || b == 32)
                    continue;

                else if (b == 61)
                {
                    if (++p > 6)
                        throw new Exception(e);
                }

                else if (p > 0)
                    throw new Exception(e);

                else
                {
                    if ((n = s.IndexOf((char)b)) < 0)
                        throw new Exception(e);

                    else if (r > 5)
                        t = t | (n << (r -= 5));

                    else
                    {
                        dest.WriteByte((byte)(t | (n >> 5 - r)));
                        t = n << (r += 3);
                    }
                }
            }
        }

        //--------------------------------------------------------------------------------

        private static bool HasRepeatedChars (string src)
        {
            for (int i = 0, l = src.Length; i < l; ++i)
                for (int j = i + 1; j < l; ++j)
                    if (src[i] == src[j]) 
                        return true;

            return false;
        }

        //--------------------------------------------------------------------------------

        private static byte GetBlockSize (byte radix)
        {
            if      (radix == 2)              radix = 8;
            else if (radix == 3)              radix = 6;
            else if (radix > 3 && radix < 7)  radix = 4;
            else if (radix > 6 && radix < 16) radix = 3;
            else                              radix = 2;

            return radix;
        }


        //--------------------------------------------------------------------------------

        private static string ByteToString (byte b, byte radix)
        {
            string s = string.Empty;

            do
            {
                s = _code[b % radix] + s;
            }
            
            while ((b = (byte)(b / radix)) > 0);

            radix = Program.GetBlockSize(radix);
            b     = (byte)s.Length;

            while (b++ < radix)
                s = _code[0] + s;

            return s;
        }

        //--------------------------------------------------------------------------------

        private static byte ByteFromBlock (byte[] b, byte radix)
        {
            byte n = 0;

            for (int c, i = 0, l = b.Length; i < l; ++i)
            {
                if ((c = _code.IndexOf((char)b[i])) < 0) throw new Exception
                (
                    string.Format
                    (
                          MSG_INVALID_BASE_SEQ + " or Wrong base-code!"
                        , radix
                    )
                );

                n = (byte)(n * radix + c);
            }

            return n;
        }

        //--------------------------------------------------------------------------------

        private static void Encode 
        (
              Stream src
            , Stream dest
            , byte   radix
        ){
            if (radix < 2)
                throw new ArgumentException(MSG_INVALID_RADIX);

            if (string.IsNullOrEmpty(_code) || _code.Length < radix || Program.HasRepeatedChars(_code))
                throw new ArgumentException(MSG_INVALID_CODE);

            int n = Program.GetBlockSize(radix);
            if (_charsperline > 0 && (_charsperline < n || _charsperline > 256 || _charsperline % n != 0))
                throw new Exception(string.Format(MSG_WRONG_LINE_WRAP, radix));

            byte[] b = new byte[_buffersize];
            long   l = src.Length;
            long   w = _charsperline - 1;
            long   p = 0;
            long   t = 0;

            for (; (n = src.Read(b, 0, _buffersize)) > 0; )
            {
                for (int i = 0; i < n; ++i)
                {
                    Program.LineWrapper(dest, t, ref w);
                    byte[] c = Encoding.ASCII.GetBytes(Program.ByteToString(b[i], radix));

                    dest.Write(c, 0, c.Length);
                    Array.Clear(c, 0, c.Length);
                    t += c.Length;
                }

                Program.Progress(p += n, l, n);
            }
        }

        //--------------------------------------------------------------------------------

        private static void Decode (Stream src, Stream dest, byte radix)
        {
            if (radix < 2)
                throw new ArgumentException(MSG_INVALID_RADIX);

            if (string.IsNullOrEmpty(_code) || _code.Length < radix || Program.HasRepeatedChars(_code))
                throw new ArgumentException(MSG_INVALID_CODE);

            long   l = src.Length;
            int    n = Program.GetBlockSize(radix);
            byte[] b = new byte[n];
            long   p = 0;
            int    c = 0;

            while ((n = src.ReadByte()) > -1)
            {
                Program.Progress(++p, l, 1);

                if ((n > 6 && n < 14) || n == 32)
                    continue;

                if (c < b.Length)
                    b[c++] = (byte)n;

                if (c == b.Length)
                {
                    dest.WriteByte(Program.ByteFromBlock(b, radix));
                    c = 0;
                }
            }

            Array.Clear(b, 0, b.Length);
        }

        //----------------------------------------------------------------------------------

        private static void ValidateSize (ref short var, short value, string emsg)
        {
            if (var == -1)
                var = value;

            else if (var != value)
                throw new Exception(emsg);
        }

        //----------------------------------------------------------------------------------

        private static void ValidateBlockSize (short value)
        {
            Program.ValidateSize(ref _blocksize, value, MSG_INVALID_BLOCK_SIZE);
        }

        //----------------------------------------------------------------------------------

        private static void ValidateKeySize (short value)
        {
            Program.ValidateSize(ref _keysize, value, MSG_INVALID_KEY_SIZE);
        }

        //----------------------------------------------------------------------------------

        private static void ValidateFeedbackSize (short value)
        {
            Program.ValidateSize(ref _feedbacksize, value, MSG_INVALID_FEEDBACK_SIZE);

            if (_feedbacksize % 8 != 0)
                throw new Exception(MSG_INVALID_FEEDBACK_SIZE);
        }

        //----------------------------------------------------------------------------------

        private static void ValidateSizes (short block, short feedback)
        {
            Program.ValidateBlockSize(block);
            Program.ValidateFeedbackSize(feedback);
        }

        //----------------------------------------------------------------------------------

        private static void ValidateSizes
        (
              ref short var
            , short     min
            , short     max
            , short     def
            , string    emsg
        ){
            if (var == -1)
                var = def;

            else if (var < min || var > max || var % 8 != 0)
                throw new Exception(emsg);
        }

        //----------------------------------------------------------------------------------

        private static void ValidateKeySize (short min, short max, short def)
        {
            Program.ValidateSizes(ref _keysize, min, max, def, MSG_INVALID_KEY_SIZE);
        }

        //----------------------------------------------------------------------------------

        private static void ValidateBlockSize (short min, short max, short def)
        {
            Program.ValidateSizes(ref _blocksize, min, max, def, MSG_INVALID_KEY_SIZE);
        }

        //----------------------------------------------------------------------------------

        private static void ValidateSizeFrom128To256 (short size)
        {
            switch (size)
            {
                case 128:
                case 192:
                case 256:
                    break;

                default:
                    throw new Exception(MSG_INVALID_KEY_SIZE);
            }
        }

        //----------------------------------------------------------------------------------

        private static void ValidateSizeFrom256to1024 (short size, string emsg)
        {
            switch (size)
            {
                case 128:
                case 192:
                case 256:
                    break;

                default:
                    throw new Exception(emsg);
            }
        }

        //--------------------------------------------------------------------------------

        private static void ClearSymmetricKey ()
        {
            if (_sk.key != null) Array.Clear(_sk.key, 0, _sk.key.Length);
            if (_sk.iv  != null) Array.Clear(_sk.iv, 0, _sk.iv.Length);
        }

        //--------------------------------------------------------------------------------

        private static void AssertSymmetricSizes 
        (
              ref short keysize
            , ref short blocksize
            , bool      hightblock
        ){
            if (blocksize > 0)
            {
                if ((hightblock && blocksize < 8) || blocksize < 4)
                    throw new Exception(MSG_INVALID_BLOCK_SIZE);

                if (((hightblock || blocksize > 64) && blocksize % 8 != 0) || (blocksize < 128 && blocksize % 4 != 0))
                    throw new Exception(MSG_INVALID_BLOCK_SIZE);

                blocksize /= (short)((hightblock || blocksize > 64) ? 8 : 4);
            }

            keysize /= 8;
        }

        //----------------------------------------------------------------------------------

        private static byte[] GetBytes (string data)
        {
            List<byte> l = new List<byte>();
            string     s = "0123456789ABCDEFabcdef";
            bool       u = _encoding == Encoding.Unicode || _encoding == Encoding.BigEndianUnicode;
            byte[]     b = null;

            for (int i = 0, n = data.Length; i < n; ++i)
            {
                if (!u && data[i] > 255)
                {
                    if (!Program.Question(MSG_UNICODE_QUESTION))
                        u = true;

                    else
                    {
                        _encoding = Encoding.Unicode;
                        Messenger.Print(Messenger.Icon.WARNING, MSG_UNICODE_CHANGE);
                        return Program.GetBytes(data);
                    }
                }

                if (_unesc || data[i] != '\\')
                    l.AddRange(b = _encoding.GetBytes(data[i].ToString()));

                else if (++i >= n || (data[i] != 'x' && data[i] != 'u'))
                    l.AddRange(b = _encoding.GetBytes(data[--i].ToString()));

                else
                {
                    if (!u && data[i] == 'u')
                    {
                        if (!Program.Question(MSG_UNICODE_QUESTION))
                            u = true;

                        else
                        {
                            _encoding = Encoding.Unicode;
                            Messenger.Print(Messenger.Icon.WARNING, MSG_UNICODE_CHANGE);
                            return Program.GetBytes(data);
                        }
                    }

                    int    j, c = data[i] == 'x' ? 1 : 2;
                    byte[]    x = new byte[c];

                    while (c-- > 0)
                    {
                        if ((j = i + 2) >= n || s.IndexOf(data[++i]) < 0 || s.IndexOf(data[j]) < 0)
                            throw new Exception("Invalid hexadecimal representation!");

                        x[c] = Convert.ToByte(data.Substring(i++, 2), 16);
                    }

                    b = Encoding.Convert
                    (
                          x.Length == 2 ? Encoding.Unicode : Encoding.ASCII
                        , _encoding
                        , x
                    );

                    l.AddRange(b);
                    Array.Clear(x, 0, x.Length);
                }

                Array.Clear(b, 0, b.Length);
            }

            b = l.ToArray();
            l.Clear();

            return b;
        }

        //--------------------------------------------------------------------------------

        private static void KeyGen
        (
              short keysize
            , short blocksize
            , bool  hightblock = false
        ){
            Program.AssertSymmetricSizes(ref keysize, ref blocksize, hightblock);
            
            bool biv = !string.IsNullOrEmpty(_iv);

            if (biv)
            {
                if (blocksize < 4)
                {
                    _iv = string.Empty;
                    Messenger.Print(Messenger.Icon.WARNING, MSG_IV_DOES_NOT_ALLOW, false, true);
                }

                else if ((_sk.iv = Program.GetBytes(_iv)).Length != blocksize)
                    throw new Exception(string.Format(MSG_INVALID_IV, blocksize));
            }

            else if (blocksize < 4)
                biv = true;

            byte[] bs, bp = Program.GetBytes(_password);

            if (string.IsNullOrEmpty(_salt)) using (MD5 md = MD5.Create())
            {
                StringBuilder sb = new StringBuilder();

                bs = md.ComputeHash(bp);
                for (int i = 0, l = bs.Length; i < l; ++i)
                    sb.Append(bs[i].ToString("x2"));

                bs = Encoding.ASCII.GetBytes(sb.ToString());
            }

            else
            {
                if (_salt.Length < 8)
                    throw new Exception("The salt must be at least 8 characters long!");

                bs = Encoding.ASCII.GetBytes(_salt);
            }

            DeriveBytes db;

            switch (_hash)
            {
                case HASH_BLAKE224:
                    db = new PBKDF2<HMACGEN<Blake224>>(bp, bs, _iterations);
                    break;

                case HASH_BLAKE256:
                    db = new PBKDF2<HMACGEN<Blake256>>(bp, bs, _iterations);
                    break;

                case HASH_BLAKE384:
                    db = new PBKDF2<HMACGEN<Blake384>>(bp, bs, _iterations);
                    break;

                case HASH_BLAKE512:
                    db = new PBKDF2<HMACGEN<Blake512>>(bp, bs, _iterations);
                    break;

                case HASH_BMW224:
                    db = new PBKDF2<HMACGEN<BlueMidnightWish224>>(bp, bs, _iterations);
                    break;

                case HASH_BMW256:
                    db = new PBKDF2<HMACGEN<BlueMidnightWish256>>(bp, bs, _iterations);
                    break;

                case HASH_BMW384:
                    db = new PBKDF2<HMACGEN<BlueMidnightWish384>>(bp, bs, _iterations);
                    break;

                case HASH_BMW512:
                    db = new PBKDF2<HMACGEN<BlueMidnightWish512>>(bp, bs, _iterations);
                    break;

                case HASH_CUBE224:
                    db = new PBKDF2<HMACGEN<CubeHash224>>(bp, bs, _iterations);
                    break;

                case HASH_CUBE256:
                    db = new PBKDF2<HMACGEN<CubeHash256>>(bp, bs, _iterations);
                    break;

                case HASH_CUBE384:
                    db = new PBKDF2<HMACGEN<CubeHash384>>(bp, bs, _iterations);
                    break;

                case HASH_CUBE512:
                    db = new PBKDF2<HMACGEN<CubeHash512>>(bp, bs, _iterations);
                    break;

                case HASH_ECHO224:
                    db = new PBKDF2<HMACGEN<Echo224>>(bp, bs, _iterations);
                    break;

                case HASH_ECHO256:
                    db = new PBKDF2<HMACGEN<Echo256>>(bp, bs, _iterations);
                    break;

                case HASH_ECHO384:
                    db = new PBKDF2<HMACGEN<Echo384>>(bp, bs, _iterations);
                    break;

                case HASH_ECHO512:
                    db = new PBKDF2<HMACGEN<Echo512>>(bp, bs, _iterations);
                    break;

                case HASH_FUGUE224:
                    db = new PBKDF2<HMACGEN<Fugue224>>(bp, bs, _iterations);
                    break;

                case HASH_FUGUE256:
                    db = new PBKDF2<HMACGEN<Fugue256>>(bp, bs, _iterations);
                    break;

                case HASH_FUGUE384:
                    db = new PBKDF2<HMACGEN<Fugue384>>(bp, bs, _iterations);
                    break;

                case HASH_FUGUE512:
                    db = new PBKDF2<HMACGEN<Fugue512>>(bp, bs, _iterations);
                    break;

                case HASH_GROESTL224:
                    db = new PBKDF2<HMACGEN<Groestl224>>(bp, bs, _iterations);
                    break;

                case HASH_GROESTL256:
                    db = new PBKDF2<HMACGEN<Groestl256>>(bp, bs, _iterations);
                    break;

                case HASH_GROESTL384:
                    db = new PBKDF2<HMACGEN<Groestl384>>(bp, bs, _iterations);
                    break;

                case HASH_GROESTL512:
                    db = new PBKDF2<HMACGEN<Groestl512>>(bp, bs, _iterations);
                    break;

                case HASH_HAMSI224:
                    db = new PBKDF2<HMACGEN<Hamsi224>>(bp, bs, _iterations);
                    break;

                case HASH_HAMSI256:
                    db = new PBKDF2<HMACGEN<Hamsi256>>(bp, bs, _iterations);
                    break;

                case HASH_HAMSI384:
                    db = new PBKDF2<HMACGEN<Hamsi384>>(bp, bs, _iterations);
                    break;

                case HASH_HAMSI512:
                    db = new PBKDF2<HMACGEN<Hamsi512>>(bp, bs, _iterations);
                    break;

                case HASH_JH224:
                    db = new PBKDF2<HMACGEN<JH224>>(bp, bs, _iterations);
                    break;

                case HASH_JH256:
                    db = new PBKDF2<HMACGEN<JH256>>(bp, bs, _iterations);
                    break;

                case HASH_JH384:
                    db = new PBKDF2<HMACGEN<JH384>>(bp, bs, _iterations);
                    break;

                case HASH_JH512:
                    db = new PBKDF2<HMACGEN<JH512>>(bp, bs, _iterations);
                    break;

                case HASH_KECCAK224:
                    db = new PBKDF2<HMACGEN<Keccak224>>(bp, bs, _iterations);
                    break;

                case HASH_KECCAK256:
                    db = new PBKDF2<HMACGEN<Keccak256>>(bp, bs, _iterations);
                    break;

                case HASH_KECCAK384:
                    db = new PBKDF2<HMACGEN<Keccak384>>(bp, bs, _iterations);
                    break;

                case HASH_KECCAK512:
                    db = new PBKDF2<HMACGEN<Keccak512>>(bp, bs, _iterations);
                    break;

                case HASH_LUFFA224:
                    db = new PBKDF2<HMACGEN<Luffa224>>(bp, bs, _iterations);
                    break;
                
                case HASH_LUFFA256:
                    db = new PBKDF2<HMACGEN<Luffa256>>(bp, bs, _iterations);
                    break;

                case HASH_LUFFA384:
                    db = new PBKDF2<HMACGEN<Luffa384>>(bp, bs, _iterations);
                    break;

                case HASH_LUFFA512:
                    db = new PBKDF2<HMACGEN<Luffa512>>(bp, bs, _iterations);
                    break;

                case HASH_SHABAL224:
                    db = new PBKDF2<HMACGEN<Shabal224>>(bp, bs, _iterations);
                    break;

                case HASH_SHABAL256:
                    db = new PBKDF2<HMACGEN<Shabal256>>(bp, bs, _iterations);
                    break;

                case HASH_SHABAL384:
                    db = new PBKDF2<HMACGEN<Shabal384>>(bp, bs, _iterations);
                    break;

                case HASH_SHABAL512:
                    db = new PBKDF2<HMACGEN<Shabal512>>(bp, bs, _iterations);
                    break;

                case HASH_SHAVITE_224:
                    db = new PBKDF2<HMACGEN<SHAvite3_224>>(bp, bs, _iterations);
                    break;

                case HASH_SHAVITE_256:
                    db = new PBKDF2<HMACGEN<SHAvite3_256>>(bp, bs, _iterations);
                    break;

                case HASH_SHAVITE_384:
                    db = new PBKDF2<HMACGEN<SHAvite3_384>>(bp, bs, _iterations);
                    break;

                case HASH_SHAVITE_512:
                    db = new PBKDF2<HMACGEN<SHAvite3_512>>(bp, bs, _iterations);
                    break;

                case HASH_SIMD224:
                    db = new PBKDF2<HMACGEN<SIMD224>>(bp, bs, _iterations);
                    break;

                case HASH_SIMD256:
                    db = new PBKDF2<HMACGEN<SIMD256>>(bp, bs, _iterations);
                    break;

                case HASH_SIMD384:
                    db = new PBKDF2<HMACGEN<SIMD384>>(bp, bs, _iterations);
                    break;

                case HASH_SIMD512:
                    db = new PBKDF2<HMACGEN<SIMD512>>(bp, bs, _iterations);
                    break;

                case HASH_SKEIN224:
                    db = new PBKDF2<HMACGEN<Skein224>>(bp, bs, _iterations);
                    break;

                case HASH_SKEIN256:
                    db = new PBKDF2<HMACGEN<Skein256>>(bp, bs, _iterations);
                    break;

                case HASH_SKEIN384:
                    db = new PBKDF2<HMACGEN<Skein384>>(bp, bs, _iterations);
                    break;

                case HASH_SKEIN512:
                    db = new PBKDF2<HMACGEN<Skein512>>(bp, bs, _iterations);
                    break;

                case HASH_RIPEMD:
                    db = new PBKDF2<HMACGEN<RIPEMD>>(bp, bs, _iterations);
                    break;

                case HASH_RIPEMD128:
                    db = new PBKDF2<HMACGEN<RIPEMD128>>(bp, bs, _iterations);
                    break;

                case HASH_RIPEMD160:
                    db = new PBKDF2<HMACRIPEMD160>(bp, bs, _iterations);
                    break;

                case HASH_RIPEMD256:
                    db = new PBKDF2<HMACGEN<RIPEMD256>>(bp, bs, _iterations);
                    break;

                case HASH_RIPEMD320:
                    db = new PBKDF2<HMACGEN<RIPEMD320>>(bp, bs, _iterations);
                    break;

                case HASH_SHA512:
                    db = new PBKDF2<HMACSHA512>(bp, bs, _iterations);
                    break;

                case HASH_SHA384:
                    db = new PBKDF2<HMACSHA384>(bp, bs, _iterations);
                    break;

                case HASH_SHA256:
                    db = new PBKDF2<HMACSHA256>(bp, bs, _iterations);
                    break;

                case HASH_SHA224:
                    db = new PBKDF2<HMACGEN<SHA224>>(bp, bs, _iterations);
                    break;

                case HASH_SHA1:
                    db = new Rfc2898DeriveBytes(bp, bs, _iterations);
                    break;

                case HASH_SHA0:
                    db = new PBKDF2<HMACGEN<SHA0>>(bp, bs, _iterations);
                    break;

                case HASH_MD5:
                    db = new PasswordDeriveBytes(bp, bs, _hash, _iterations);
                    break;

                case HASH_MD4:
                    db = new PBKDF2<HMACGEN<MD4>>(bp, bs, _iterations);
                    break;

                case HASH_MD2:
                    db = new PBKDF2<HMACGEN<MD2>>(bp, bs, _iterations);
                    break;

                case GOST:
                    db = new PBKDF2<HMACGEN<Gost>>(bp, bs, _iterations);
                    break;

                case HASH_GRINDAHL256:
                    db = new PBKDF2<HMACGEN<Grindahl256>>(bp, bs, _iterations);
                    break;

                case HASH_GRINDAHL512:
                    db = new PBKDF2<HMACGEN<Grindahl512>>(bp, bs, _iterations);
                    break;

                case HASH_HAS160:
                    db = new PBKDF2<HMACGEN<HAS160>>(bp, bs, _iterations);
                    break;

                case HASH_HAVAL3_128:
                    db = new PBKDF2<HMACGEN<Haval_3_128>>(bp, bs, _iterations);
                    break;

                case HASH_HAVAL3_160:
                    db = new PBKDF2<HMACGEN<Haval_3_160>>(bp, bs, _iterations);
                    break;

                case HASH_HAVAL3_192:
                    db = new PBKDF2<HMACGEN<Haval_3_192>>(bp, bs, _iterations);
                    break;

                case HASH_HAVAL3_224:
                    db = new PBKDF2<HMACGEN<Haval_3_224>>(bp, bs, _iterations);
                    break;

                case HASH_HAVAL3_256:
                    db = new PBKDF2<HMACGEN<Haval_3_256>>(bp, bs, _iterations);
                    break;

                case HASH_HAVAL4_128:
                    db = new PBKDF2<HMACGEN<Haval_4_128>>(bp, bs, _iterations);
                    break;

                case HASH_HAVAL4_160:
                    db = new PBKDF2<HMACGEN<Haval_4_160>>(bp, bs, _iterations);
                    break;

                case HASH_HAVAL4_192:
                    db = new PBKDF2<HMACGEN<Haval_4_192>>(bp, bs, _iterations);
                    break;

                case HASH_HAVAL4_224:
                    db = new PBKDF2<HMACGEN<Haval_4_224>>(bp, bs, _iterations);
                    break;

                case HASH_HAVAL4_256:
                    db = new PBKDF2<HMACGEN<Haval_4_256>>(bp, bs, _iterations);
                    break;

                case HASH_HAVAL5_128:
                    db = new PBKDF2<HMACGEN<Haval_5_128>>(bp, bs, _iterations);
                    break;

                case HASH_HAVAL5_160:
                    db = new PBKDF2<HMACGEN<Haval_5_160>>(bp, bs, _iterations);
                    break;

                case HASH_HAVAL5_192:
                    db = new PBKDF2<HMACGEN<Haval_5_192>>(bp, bs, _iterations);
                    break;

                case HASH_HAVAL5_224:
                    db = new PBKDF2<HMACGEN<Haval_5_224>>(bp, bs, _iterations);
                    break;

                case HASH_HAVAL5_256:
                    db = new PBKDF2<HMACGEN<Haval_5_256>>(bp, bs, _iterations);
                    break;

                case HASH_PANAMA:
                    db = new PBKDF2<HMACGEN<Panama>>(bp, bs, _iterations);
                    break;

                case HASH_RG32:
                    db = new PBKDF2<HMACGEN<RadioGatun32>>(bp, bs, _iterations);
                    break;

                case HASH_RG64:
                    db = new PBKDF2<HMACGEN<RadioGatun64>>(bp, bs, _iterations);
                    break;

                case HASH_SNEFRU4_128:
                    db = new PBKDF2<HMACGEN<Snefru_4_128>>(bp, bs, _iterations);
                    break;

                case HASH_SNEFRU4_256:
                    db = new PBKDF2<HMACGEN<Snefru_4_256>>(bp, bs, _iterations);
                    break;

                case HASH_SNEFRU8_128:
                    db = new PBKDF2<HMACGEN<Snefru_8_128>>(bp, bs, _iterations);
                    break;

                case HASH_SNEFRU8_256:
                    db = new PBKDF2<HMACGEN<Snefru_8_256>>(bp, bs, _iterations);
                    break;

                case HASH_TIGER2:
                    db = new PBKDF2<HMACGEN<Tiger2>>(bp, bs, _iterations);
                    break;

                case HASH_TIGER3_192:
                    db = new PBKDF2<HMACGEN<Tiger_3_192>>(bp, bs, _iterations);
                    break;

                case HASH_TIGER4_192:
                    db = new PBKDF2<HMACGEN<Tiger_4_192>>(bp, bs, _iterations);
                    break;

                case HASH_WHIRLPOOL:
                    db = new PBKDF2<HMACGEN<Whirlpool>>(bp, bs, _iterations);
                    break;

                case HASH_AP:
                    db = new PBKDF2<HMACGEN<AP>>(bp, bs, _iterations);
                    break;

                case HASH_BERNSTEIN:
                    db = new PBKDF2<HMACGEN<Bernstein>>(bp, bs, _iterations);
                    break;

                case HASH_BERNSTEIN1:
                    db = new PBKDF2<HMACGEN<Bernstein1>>(bp, bs, _iterations);
                    break;

                case HASH_BKDR:
                    db = new PBKDF2<HMACGEN<BKDR>>(bp, bs, _iterations);
                    break;

                case HASH_DEK:
                    db = new PBKDF2<HMACGEN<DEK>>(bp, bs, _iterations);
                    break;

                case HASH_DJB:
                    db = new PBKDF2<HMACGEN<DJB>>(bp, bs, _iterations);
                    break;

                case HASH_DOTNET:
                    db = new PBKDF2<HMACGEN<DotNet>>(bp, bs, _iterations);
                    break;

                case HASH_ELF:
                    db = new PBKDF2<HMACGEN<ELF>>(bp, bs, _iterations);
                    break;

                case HASH_FNV:
                    db = new PBKDF2<HMACGEN<FNV>>(bp, bs, _iterations);
                    break;

                case HASH_FNV1A:
                    db = new PBKDF2<HMACGEN<FNV1a>>(bp, bs, _iterations);
                    break;

                case HASH_FNV64:
                    db = new PBKDF2<HMACGEN<FNV64>>(bp, bs, _iterations);
                    break;

                case HASH_FNV1A64:
                    db = new PBKDF2<HMACGEN<FNV1a64>>(bp, bs, _iterations);
                    break;

                case HASH_JENKINS3:
                    db = new PBKDF2<HMACGEN<Jenkins3>>(bp, bs, _iterations);
                    break;

                case HASH_JS:
                    db = new PBKDF2<HMACGEN<JS>>(bp, bs, _iterations);
                    break;

                case HASH_MURMUR2:
                    db = new PBKDF2<HMACGEN<Murmur2>>(bp, bs, _iterations);
                    break;

                case HASH_MURMUR2_64:
                    db = new PBKDF2<HMACGEN<Murmur2_64>>(bp, bs, _iterations);
                    break;

                case HASH_MURMUR3:
                    db = new PBKDF2<HMACGEN<Murmur3>>(bp, bs, _iterations);
                    break;

                case HASH_ONEATTIME:
                    db = new PBKDF2<HMACGEN<OneAtTime>>(bp, bs, _iterations);
                    break;

                case HASH_PJW:
                    db = new PBKDF2<HMACGEN<PJW>>(bp, bs, _iterations);
                    break;

                case HASH_ROTATING:
                    db = new PBKDF2<HMACGEN<Rotating>>(bp, bs, _iterations);
                    break;

                case HASH_RS:
                    db = new PBKDF2<HMACGEN<RS>>(bp, bs, _iterations);
                    break;

                case HASH_SDBM:
                    db = new PBKDF2<HMACGEN<SDBM>>(bp, bs, _iterations);
                    break;

                case HASH_SHIFTANDXOR:
                    db = new PBKDF2<HMACGEN<ShiftAndXor>>(bp, bs, _iterations);
                    break;

                case HASH_SUPERFAST:
                    db = new PBKDF2<HMACGEN<SuperFast>>(bp, bs, _iterations);
                    break;

                case HASH_SIPHASH:
                    db = new PBKDF2<HMACGEN<HashLib.Hash64.SipHash>>(bp, bs, _iterations);
                    break;

                case HASH_MURMUR3_128:
                    db = new PBKDF2<HMACGEN<Murmur3_128>>(bp, bs, _iterations);
                    break;

                default:
                    throw new Exception(MSG_INVALID_HASH);
            }

            if (biv)
                _sk.key = db.GetBytes(keysize);

            else
            {
                byte[] b = db.GetBytes(keysize + blocksize);
                _sk.key  = new byte[keysize];
                _sk.iv   = new byte[blocksize];

                Buffer.BlockCopy(b, 0, _sk.key, 0, keysize);
                Buffer.BlockCopy(b, keysize, _sk.iv, 0, blocksize);
                Array.Clear(b, 0, b.Length);
            }

            db.Reset();
            Array.Clear(bp, 0, bp.Length);
            Array.Clear(bs, 0, bs.Length);
        }

        //----------------------------------------------------------------------------------

        private static void SetSymmetricKey
        (
              short keysize
            , short blocksize
            , bool  hightblock
        ){
            Program.AssertSymmetricSizes(ref keysize, ref blocksize, hightblock);

            if ((_sk.key = Program.GetBytes(_key)).Length != keysize)
                throw new Exception(MSG_INVALID_KEY_SIZE);

            if (blocksize > 0)
            {
                if (string.IsNullOrEmpty(_iv) || (_sk.iv = Program.GetBytes(_iv)).Length != blocksize)
                    throw new Exception(string.Format(MSG_INVALID_IV, blocksize));
            }

            else if (!string.IsNullOrEmpty(_iv))
            {
                _iv = string.Empty;
                Messenger.Print(Messenger.Icon.WARNING, MSG_IV_DOES_NOT_ALLOW, false, true);
            }
        }

        //----------------------------------------------------------------------------------

        private static IBlockCipherPadding GetBouncyCastlePadding ()
        {
            switch (_padding)
            {
                case CryptPadding.PKCS7:
                    return new Pkcs7Padding();

                case CryptPadding.ANSIX923:
                    return new X923Padding();

                case CryptPadding.ISO10126:
                    return new ISO10126d2Padding();

                case CryptPadding.ISO7816:
                    return new ISO7816d4Padding();
                
                case CryptPadding.TBC:
                    return new TbcPadding();

                default:
                    throw new Exception(MSG_INVALID_PADDING_MODE);
            }
        }

        //----------------------------------------------------------------------------------

        private static void ValidateIntrinsicPadding ()
        {
            switch (_padding)
            {
                case CryptPadding.PKCS7:
                case CryptPadding.ANSIX923:
                case CryptPadding.ISO10126:
                case CryptPadding.Zeros:
                    break;

                default:
                    throw new Exception(MSG_INVALID_PADDING_MODE);
            }
        }

        //----------------------------------------------------------------------------------

        private static IBlockCipher GetBlockCipherMode (IBlockCipher engine)
        {
            switch (_ciphermode)
            {
                case CipherMode.CBC:
                    return new CbcBlockCipher(engine);

                case CipherMode.CFB:
                    return new CfbBlockCipher(engine, engine.GetBlockSize() * 8);

                case CipherMode.OFB:
                    return new OfbBlockCipher(engine, engine.GetBlockSize() * 8);

                default:
                    throw new Exception(MSG_INVALID_CIPHER_MODE);
            }
        }

        //----------------------------------------------------------------------------------

        private static void Write (Stream src, Stream dest, long srclen)
        {
            byte[] b = new byte[_buffersize];
            long   n = 0;

            for (int c; (c = src.Read(b, 0, _buffersize)) > 0; )
            {
                dest.Write(b, 0, c);
                Program.Progress(n += c, srclen, c);
            }

            Array.Clear(b, 0, b.Length);

            if (_percent < 100)
                Program.Progress(srclen, srclen, 0);
        }

        //----------------------------------------------------------------------------------

        private static void Crypt (SymmetricAlgorithm sa, Stream src, Stream dest)
        {
            if (_cop == CryptOperation.ENCRYPT)
            {
                using (ICryptoTransform ct = sa.CreateEncryptor(_sk.key, _sk.iv))
                {
                    using (CryptoStream cs = new CryptoStream(dest, ct, CryptoStreamMode.Write))
                    {
                        Program.Write(src, cs, src.Length);
                        cs.FlushFinalBlock();
                    }
                }
            }

            else using (ICryptoTransform ct = sa.CreateDecryptor(_sk.key, _sk.iv))
            {
                using (CryptoStream cs = new CryptoStream(src, ct, CryptoStreamMode.Read))
                {
                    Program.Write(cs, dest, src.Length);
                }
            }
        }

        //----------------------------------------------------------------------------------

        private static void Rc2Crypt (Stream src, Stream dest)
        {
            if (_without_iv)
            {
                BufferedBlockCipher bc = new PaddedBufferedBlockCipher
                (
                      Program.GetBlockCipherMode(new RC2Engine())
                    , Program.GetBouncyCastlePadding()
                );

                bc.Init(_cop == CryptOperation.ENCRYPT, new KeyParameter(_sk.key));
                Program.Write(bc, src, dest);
            }

            else using (RC2CryptoServiceProvider sp = new RC2CryptoServiceProvider())
            {
                sp.Mode      = _ciphermode;
                sp.Padding   = (PaddingMode)_padding;
                sp.KeySize   = _keysize;
                sp.BlockSize = _blocksize;

                Program.Crypt(sp, src, dest);
            }
        }

        //----------------------------------------------------------------------------------

        private static void DesCrypt (Stream src, Stream dest)
        {

            if (_without_iv)
            {
                BufferedBlockCipher bc = new PaddedBufferedBlockCipher
                (
                      Program.GetBlockCipherMode(new DesEngine())
                    , Program.GetBouncyCastlePadding()
                );

                bc.Init(_cop == CryptOperation.ENCRYPT, new KeyParameter(_sk.key));
                Program.Write(bc, src, dest);
            }

            else using (DESCryptoServiceProvider sp = new DESCryptoServiceProvider())
            {
                sp.Mode      = _ciphermode;
                sp.Padding   = (PaddingMode)_padding;
                sp.KeySize   = _keysize;
                sp.BlockSize = _blocksize;

                Program.Crypt(sp, src, dest);
            }
        }

        //----------------------------------------------------------------------------------

        private static void TripleDesCrypt (Stream src, Stream dest)
        {
            if (_without_iv)
            {
                BufferedBlockCipher bc = new PaddedBufferedBlockCipher
                (
                      Program.GetBlockCipherMode(new DesEdeEngine())
                    , Program.GetBouncyCastlePadding()
                );

                bc.Init(_cop == CryptOperation.ENCRYPT, new KeyParameter(_sk.key));
                Program.Write(bc, src, dest);
            }

            else using (TripleDESCryptoServiceProvider sp = new TripleDESCryptoServiceProvider())
            {
                sp.Mode      = _ciphermode;
                sp.Padding   = (PaddingMode)_padding;
                sp.KeySize   = _keysize;
                sp.BlockSize = _blocksize;

                Program.Crypt(sp, src, dest);
            }
        }

        //----------------------------------------------------------------------------------

        private static void RijndaelCrypt (Stream src, Stream dest)
        {
            if (_without_iv)
            {
                BufferedBlockCipher bc = new PaddedBufferedBlockCipher
                (
                      Program.GetBlockCipherMode(new RijndaelEngine(_blocksize))
                    , Program.GetBouncyCastlePadding()
                );

                bc.Init(_cop == CryptOperation.ENCRYPT, new KeyParameter(_sk.key));
                Program.Write(bc, src, dest);
            }

            else using (RijndaelManaged rm = new RijndaelManaged())
            {
                rm.Mode         = _ciphermode;
                rm.Padding      = (PaddingMode)_padding;
                rm.KeySize      = _keysize;
                rm.BlockSize    = _blocksize;
                rm.FeedbackSize = _feedbacksize;

                Program.Crypt(rm, src, dest);
            }
        }

        //----------------------------------------------------------------------------------

        private static void AesCrypt (Stream src, Stream dest)
        {
            if (_without_iv)
            {
                BufferedBlockCipher bc = new PaddedBufferedBlockCipher
                (
                      Program.GetBlockCipherMode(new AesEngine())
                    , Program.GetBouncyCastlePadding()
                );

                bc.Init(_cop == CryptOperation.ENCRYPT, new KeyParameter(_sk.key));
                Program.Write(bc, src, dest);
            }

            else Program.RijndaelCrypt(src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void MarsCrypt (Stream src, Stream dest)
        {
            using (MarsManaged mm = new MarsManaged())
            {
                mm.KeySize   = _keysize;
                mm.BlockSize = _blocksize;
                mm.Mode      = _ciphermode;
                mm.Padding   = (PaddingMode)_padding;

                Program.Crypt(mm, src, dest);
            }
        }

        //----------------------------------------------------------------------------------

        private static void RsaCrypt
        (
              RSACryptoServiceProvider rsa
            , Stream                   src
            , Stream                   dest
            , bool                     cleanse = false
        ){
            if (_rsa_bc)
            {
                RsaKeyParameters k;
                RSAParameters    p = rsa.ExportParameters(_cop == CryptOperation.DECRYPT);

                if (_cop == CryptOperation.ENCRYPT) k = new RsaKeyParameters
                (
                      false
                    , new BigInteger(1, p.Modulus)
                    , new BigInteger(1, p.Exponent)
                );

                else k = new RsaPrivateCrtKeyParameters
                (
                      new BigInteger(1, p.Modulus)
                    , new BigInteger(1, p.Exponent)
                    , new BigInteger(1, p.D)
                    , new BigInteger(1, p.P)
                    , new BigInteger(1, p.Q)
                    , new BigInteger(1, p.DP)
                    , new BigInteger(1, p.DQ)
                    , new BigInteger(1, p.InverseQ)
                );

                IAsymmetricBlockCipher abc;

                if (_padding == CryptPadding.OAEP) 
                    abc = Program.GetOaepEncoding(new RsaEngine(), k.Modulus.BitLength);

                else if (_padding == CryptPadding.ISO9796D1)
                    abc = new ISO9796d1Encoding(new RsaEngine());

                else if (_padding == CryptPadding.PKCS1)
                    abc = new Pkcs1Encoding(new RsaEngine());

                else throw new Exception(MSG_INVALID_PADDING_MODE);

                BufferedAsymmetricBlockCipher bac = new BufferedAsymmetricBlockCipher(abc);

                bac.Init(_cop == CryptOperation.ENCRYPT, k);
                Program.Write(bac, bac.GetBlockSize(), src, dest);
            }

            else
            {
                int n, l = rsa.KeySize / 8;

                if (_cop == CryptOperation.ENCRYPT)
                    l -= 42;

                byte[] a = new byte[l];
                long   p = 0;
                long   z = src.Length;

                while ((n = src.Read(a, 0, l)) > 0)
                {
                    byte[] c;

                    if (n < l)
                    {
                        Array.Copy(a, c = new byte[n], l = n);
                        a = c;
                    }

                    if (_cop == CryptOperation.ENCRYPT)
                         c = rsa.Encrypt(a, _padding == CryptPadding.OAEP);

                    else c = rsa.Decrypt(a, _padding == CryptPadding.OAEP);

                    dest.Write(c, 0, c.Length);
                    Array.Clear(c, 0, c.Length);
                    Program.Progress(p += n, z, n);
                }
            }

            if (cleanse)
                rsa.Clear();
        }

        //----------------------------------------------------------------------------------

        private static void RsaValidateKeySize ()
        {
            int min = 384;
            int max = 16384;

            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
            {
                foreach (KeySizes k in rsa.LegalKeySizes)
                {
                    min = k.MinSize;
                    max = k.MaxSize;
                }
            }

            if (_keysize == -1)
                _keysize = (short)(max > 512 ? 1024 : max);

            else if (_keysize < min || _keysize > max || _keysize % 8 != 0)
                throw new Exception(MSG_INVALID_KEY_SIZE);
        }

        //----------------------------------------------------------------------------------

        private static void RsaImportKey (RSACryptoServiceProvider rsa, string path)
        {
            path = File.ReadAllText(path);

            if (_format == CryptFormat.UNKNOWN)
                _format = path.IndexOf('<') != -1 ? CryptFormat.XML : CryptFormat.BLOB;

            if (_format == CryptFormat.BLOB)
            {
                byte[] b = Program.Base64Decode(path);

                rsa.ImportCspBlob(b);
                Array.Clear(b, 0, b.Length);
            }

            else if (_format == CryptFormat.XML)
                rsa.FromXmlString(path);

            _hasprivatekey = !rsa.PublicOnly;
        }

        //----------------------------------------------------------------------------------

        private static void ValidateKeyPairFiles (bool pbk = true, bool pvk = true)
        {
            if (pbk && !Program.ValidatePath(_public_key))
                throw new Exception(MSG_INVALID_PUBLIC_KEY);

            if (pvk && !Program.ValidatePath(_private_key))
                throw new Exception(MSG_INVALID_PRIVATE_KEY);

            Program.OverwriteFileCheck(_public_key);
            Program.OverwriteFileCheck(_private_key);
        }

        //----------------------------------------------------------------------------------

        private static void RsaBouncyCastlePrivateKeyGen (RSACryptoServiceProvider rsa)
        { 
            RsaKeyPairGenerator     kpg = new RsaKeyPairGenerator();
            KeyGenerationParameters kgp = new KeyGenerationParameters
            (
                   new SecureRandom()
                , _keysize
            );

            kpg.Init(kgp);

            AsymmetricCipherKeyPair    akp = kpg.GenerateKeyPair();
            RsaPrivateCrtKeyParameters key = (RsaPrivateCrtKeyParameters)akp.Private;
            RSAParameters              rps = new RSAParameters();

            rps.Modulus  = key.Modulus.ToByteArrayUnsigned();
            rps.Exponent = key.PublicExponent.ToByteArrayUnsigned();
            rps.D        = key.Exponent.ToByteArrayUnsigned();
            rps.P        = key.P.ToByteArrayUnsigned();
            rps.Q        = key.Q.ToByteArrayUnsigned();
            rps.DP       = key.DP.ToByteArrayUnsigned();
            rps.DQ       = key.DQ.ToByteArrayUnsigned();
            rps.InverseQ = key.QInv.ToByteArrayUnsigned();

            rsa.ImportParameters(rps);
        }

        //----------------------------------------------------------------------------------

        private static void RsaKeyPairGen (RSACryptoServiceProvider rsa)
        {
            Program.ValidateKeyPairFiles(true, _hasprivatekey);

            if (_rsa_bc)
                Program.RsaBouncyCastlePrivateKeyGen(rsa);
           
            if (_format == CryptFormat.UNKNOWN)
                _format = CryptFormat.BLOB;

            if (_format == CryptFormat.BLOB)
            {
                byte[] b = rsa.ExportCspBlob(false);

                File.WriteAllBytes(_public_key, Program.Base64Encode(b));
                Array.Clear(b, 0, b.Length);

                if (rsa.PublicOnly)
                    Messenger.Print(Messenger.Icon.WARNING, MSG_PUBLIC_KEY_ONLY);

                else
                {
                    b = rsa.ExportCspBlob(true);
                    File.WriteAllBytes(_private_key, Program.Base64Encode(b));
                    Array.Clear(b, 0, b.Length);
                }
            }

            else if (_format == CryptFormat.XML)
            {
                File.WriteAllText(_public_key, rsa.ToXmlString(false));

                if (!_hasprivatekey)
                    Messenger.Print(Messenger.Icon.WARNING, MSG_PUBLIC_KEY_ONLY);

                else File.WriteAllText(_private_key, rsa.ToXmlString(true));
            }

            else throw new Exception("Invalid format for RSA mode!");
        }

        //----------------------------------------------------------------------------------

        private static RSACryptoServiceProvider CertificateToRsa 
        (
              X509Certificate2 cer
            , CryptOperation   cop
        ){
            _hasprivatekey = cer.HasPrivateKey;

            if (cop == CryptOperation.DECRYPT && !_hasprivatekey)
                throw new Exception("The specified certificate has no private key!");

            RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)
            (
                cop == CryptOperation.ENCRYPT || !_hasprivatekey ? cer.PublicKey.Key : cer.PrivateKey
            );

            return rsa;
        }

        //----------------------------------------------------------------------------------

        private static RSACryptoServiceProvider GetRsaFromCertificateFile (CryptOperation cop)
        {
            X509Certificate2         cer = null;
            RSACryptoServiceProvider rsa = null;

            if (!File.Exists(_cerfile)) throw new Exception
            (
                String.Format
                (
                      MSG_FILE_WAS_NOT_FOUND
                    , Path.GetFileName(_cerfile)
                )
            );

            try
            {
                cer = new X509Certificate2(_cerfile, _password, X509KeyStorageFlags.Exportable);
            }

            catch (CryptographicException e)
            {
                if (-2147024810 == Marshal.GetHRForException(e))
                {
                    if (!string.IsNullOrEmpty(_password))
                    {
                        if (_raisepwd)
                            throw new Exception(MSG_INCORRECT_PASSWORD);

                        Messenger.Print
                        (
                              Messenger.Icon.ERROR
                            , MSG_INCORRECT_PASSWORD +
                              MSG_PLEASE_TRY_AGAIN
                            , false
                            , true
                        );

                        Program.ExceptionControl(-2147024810);
                        _password = string.Empty;
                    }

                    Program.DefinePassword(true);
                    return Program.GetRsaFromCertificateFile(cop);
                }
            }

            if (cer != null)
                rsa = Program.CertificateToRsa(cer, cop);

            else                                                                                // PEM or DER format:
            {
                byte[] dat = null;
                byte[] bsd = File.ReadAllBytes(_cerfile);

                CspParameters cp = new CspParameters();
                cp.Flags = CspProviderFlags.UseMachineKeyStore;

                if (cop == CryptOperation.ENCRYPT)
                {
                    if ((dat = OpenSSL.GetRawData(bsd, "CERTIFICATE")) != null)
                    {
                        rsa = Program.CertificateToRsa(new X509Certificate2(dat), cop);
                        Array.Clear(dat, 0, dat.Length);
                    }

                    else if ((dat = OpenSSL.GetRawData(bsd, "PUBLIC KEY")) != null)
                    {
                        rsa = new RSACryptoServiceProvider(cp);
                        OpenSSL.SetPublicKey(rsa, dat);
                        Array.Clear(dat, 0, dat.Length);
                    }

                    else
                    {
                        Messenger.Print
                        (
                              Messenger.Icon.WARNING
                            , "No public key or certificate was found,\n" + 
                              "It will try with the private key!\n"
                        );

                        cop = CryptOperation.DECRYPT;
                    }
                }

                if (cop == CryptOperation.DECRYPT)
                {
                    string spk = "PRIVATE KEY";
                    string cod = string.Empty;
                    string alg = string.Empty;

                    rsa = new RSACryptoServiceProvider(cp);

                    while (true)
                    {
                        try
                        {
                            if ((dat = OpenSSL.GetRawData(bsd, "ENCRYPTED " + spk)) != null)
                            {
                                Program.DefinePassword(true);
                                OpenSSL.SetEncryptedPrivateKey(rsa, dat, _password);
                                Array.Clear(dat, 0, dat.Length);
                            }

                            else if ((dat = OpenSSL.GetRawData(bsd, "RSA " + spk, ref cod, ref alg)) != null)
                            {
                                if (!string.IsNullOrEmpty(cod))
                                {
                                    Program.DefinePassword(true);

                                    byte[] d = dat;
                                    dat = OpenSSL.DecryptRsaPrivateKey(alg, cod, _password, d);
                                    Array.Clear(d, 0, d.Length);
                                }

                                OpenSSL.SetRsaPrivateKey(rsa, dat);
                                Array.Clear(dat, 0, dat.Length);
                            }

                            else if ((dat = OpenSSL.GetRawData(bsd, spk)) != null)
                            {
                                OpenSSL.SetPrivateKey(rsa, dat);
                                Array.Clear(dat, 0, dat.Length);
                            }

                            else throw new Exception("No private key was found!");

                            _hasprivatekey = true;
                            break;
                        }

                        catch (Exception e)
                        {
                            switch (Marshal.GetHRForException(e))
                            {
                                case -2146233296:
                                case -2146893819:
                                    if (_raisepwd)
                                        throw new Exception(MSG_INCORRECT_PASSWORD);

                                    Messenger.Print
                                    (
                                          Messenger.Icon.ERROR
                                        , MSG_INCORRECT_PASSWORD +
                                          MSG_PLEASE_TRY_AGAIN
                                        , false
                                        , true
                                    );

                                    Program.ExceptionControl(-2146233296);
                                    _password = string.Empty;
                                    break;
                            }
                        }
                    }
                }

                Array.Clear(bsd, 0, bsd.Length);
            }
            
            return rsa;
        }

        //----------------------------------------------------------------------------------

        private static RSACryptoServiceProvider GetRsaFromCertificateStore ()
        { 

            StoreLocation[]  loc = {StoreLocation.CurrentUser, StoreLocation.LocalMachine};
            X509Certificate2 cer = null;
            string           scn = "cn=" + _cerstore;

            foreach (StoreLocation l in loc) if (cer == null)
            {
                X509Store store = new X509Store(l);
                store.Open(OpenFlags.ReadOnly);

                foreach (X509Certificate2 c in store.Certificates) 
                {
                    foreach (string s in c.Subject.Split(','))
                    {
                        if (s.Equals(scn, StringComparison.CurrentCultureIgnoreCase))
                        {
                            cer = c;
                            break;
                        }
                    }

                    if (cer != null)
                        break;
                }

                store.Close();
            }

            if (cer == null) 
                throw new Exception("\"" + _cerstore + "\" certificate was not found!");

            return Program.CertificateToRsa(cer, _cop);
        }

        //----------------------------------------------------------------------------------

        private static PgpKeyRingGenerator DsaKeyRingGen ()
        {
            DsaKeyPairGenerator        kpg = new DsaKeyPairGenerator();
            DsaParametersGenerator     dpg = new DsaParametersGenerator();
            DsaKeyGenerationParameters kgp;

            dpg.Init(1024, 64, new SecureRandom());
            kgp = new DsaKeyGenerationParameters(new SecureRandom(), dpg.GenerateParameters());
            kpg.Init(kgp);

            return new PgpKeyRingGenerator
            (
                  PgpSignature.DefaultCertification
                , new PgpKeyPair
                  (
                        PublicKeyAlgorithmTag.Dsa
                      , kpg.GenerateKeyPair()
                      , DateTime.Now
                  )
                , _pgp_id
                , _ska
                , _password.ToCharArray()
                , _sha1
                , null
                , null
                , new SecureRandom()
            );
        }

        //----------------------------------------------------------------------------------
        
        private static AsymmetricCipherKeyPair GetCurveKeyPair (string algorithm)
        {
            DerObjectIdentifier oid = null;

            switch (_curvestore)
            {
                case CUSTOM:
                    oid = CustomNamedCurves.GetOid(_curve);
                    break;

                case ANSSI:
                    oid = AnssiNamedCurves.GetOid(_curve);
                    break;

                case TELETRUST:
                    oid = TeleTrusTNamedCurves.GetOid(_curve);
                    break;

                case NIST:
                    oid = NistNamedCurves.GetOid(_curve);
                    break;

                case SEC:
                    oid = SecNamedCurves.GetOid(_curve);
                    break;

                case X962:
                    oid = X962NamedCurves.GetOid(_curve);
                    break;

                case GOST:
                    oid = ECGost3410NamedCurves.GetOid(_curve);
                    break;

                default:
                    throw new Exception(MSG_INVALID_CURVE_STORE);
            }

            if (oid == null)
                throw new Exception("Curve not found!");

            ECKeyPairGenerator      kpg = new ECKeyPairGenerator(algorithm);
            KeyGenerationParameters kgp = new ECKeyGenerationParameters(oid, new SecureRandom());

            kpg.Init(kgp);
            return kpg.GenerateKeyPair();
        }

        //----------------------------------------------------------------------------------

        private static PgpKeyRingGenerator EcdsaKeyRingGen ()
        {
            return new PgpKeyRingGenerator
            (
                  PgpSignature.DefaultCertification
                , new PgpKeyPair
                  (
                        PublicKeyAlgorithmTag.ECDsa
                      , Program.GetCurveKeyPair(ECDSA)
                      , DateTime.Now
                  )
                , _pgp_id
                , _ska
                , _password.ToCharArray()
                , _sha1
                , null
                , null
                , new SecureRandom()
            );
        }

        //----------------------------------------------------------------------------------

        private static PgpKeyRingGenerator EcdhKeyRingGen ()
        {
            PgpKeyRingGenerator krg = Program.EcdsaKeyRingGen();

            krg.AddSubKey
            (
                new PgpKeyPair
                (
                      PublicKeyAlgorithmTag.ECDH
                    , Program.GetCurveKeyPair(ECDH)
                    , DateTime.Now
                )
            );

            return krg;
        }

        //----------------------------------------------------------------------------------

        private static PgpSecretKey GetPgpSecretKey (RSACryptoServiceProvider rsa)
        {
            return new PgpSecretKey
            (
                  PgpSignature.DefaultCertification
                , new PgpKeyPair
                  (
                        Program.GetPgpPublicKeyFromRsa(rsa)
                      , Program.GetPgpPrivateKeyFromRsa(rsa)
                  )
                , _pgp_id
                , _ska
                , _password.ToCharArray()
                , _sha1
                , null
                , null
                , new SecureRandom()
           );
        }

        //----------------------------------------------------------------------------------

        private static PgpKeyRingGenerator GetKeyRingGen ()
        {
            switch (_pgp_master)
            {
                case DSA:
                    return Program.DsaKeyRingGen();

                case ECDSA:
                    return Program.EcdsaKeyRingGen();

                case ECDH:
                    return Program.EcdhKeyRingGen();

                default:
                    throw new Exception("Invalid Pgp master key type!");
            }
        }

        //----------------------------------------------------------------------------------

        private static void PgpRsaKeyPairGen
        (
              bool                     armored
            , RSACryptoServiceProvider guest = null
        ){
            PgpSecretKey psk = null;
            PgpPublicKey pbk = null;

            if (guest != null)
            {
                Program.ValidateKeyPairFiles(true, _hasprivatekey);

                if (_hasprivatekey)
                {
                    Program.DefinePassword(true);
                    psk = Program.GetPgpSecretKey(guest);
                }

                else
                {
                    Messenger.Print(Messenger.Icon.WARNING, MSG_PUBLIC_KEY_ONLY);
                    pbk = Program.GetPgpPublicKeyFromRsa(guest);
                }
            }

            else
            {
                Program.ValidateKeyPairFiles();
                Program.RsaValidateKeySize();
                Program.DefinePassword(true);

                using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(_keysize))
                {
                    if (_rsa_bc)
                        Program.RsaBouncyCastlePrivateKeyGen(rsa);

                    psk = Program.GetPgpSecretKey(rsa);
                }
            }

            if (string.IsNullOrEmpty(_pgp_master))
            {
                if (psk != null)
                {
                    using (FileStream fspvk = File.Create(_private_key))
                        using (Stream stm = armored ? (Stream)new ArmoredOutputStream(fspvk) : fspvk)
                            psk.Encode(stm);

                    pbk = psk.PublicKey;
                }

                if (pbk != null)
                    using (FileStream fspbk = File.Create(_public_key))
                        using (Stream stm = armored ? (Stream)new ArmoredOutputStream(fspbk) : fspbk)
                            pbk.Encode(stm);
            }

            else 
            {
                if (psk == null)
                    throw new Exception(MSG_INVALID_PRIVATE_KEY);

                PgpKeyRingGenerator krg = Program.GetKeyRingGen();
                PgpPrivateKey       pvk = psk.ExtractPrivateKey(_password.ToCharArray());

                if (pbk == null)
                    pbk = psk.PublicKey;

                krg.AddSubKey(new PgpKeyPair(pbk, pvk));

                using (FileStream fspvk = File.Create(_private_key))
                    using (Stream stm = armored ? (Stream)new ArmoredOutputStream(fspvk) : fspvk)
                        krg.GenerateSecretKeyRing().Encode(stm);

                using (FileStream fspbk = File.Create(_public_key))
                    using (Stream stm = armored ? (Stream)new ArmoredOutputStream(fspbk) : fspbk)
                        krg.GeneratePublicKeyRing().Encode(stm);
            }
        }

        //----------------------------------------------------------------------------------

        private static void PgpElGamalKeyPairGen
        (
              bool                    armored
            , AsymmetricCipherKeyPair guest = null
        ){
            Program.ValidateKeyPairFiles();
            Program.DefinePassword(true);

            if (guest != null)
            {
                if 
                (
                    guest.Private == null || !(guest.Private is ElGamalPrivateKeyParameters) || 
                    guest.Public  == null || !(guest.Public  is ElGamalPublicKeyParameters)
                ){
                    throw new Exception(MSG_INVALID_KEY_PAIR);
                }
            }

            else guest = ElGamalKeyPairGen(false);

            if (string.IsNullOrEmpty(_pgp_master))
                _pgp_master = DSA;

            PgpKeyRingGenerator krg = Program.GetKeyRingGen();

            krg.AddSubKey
            (
                  new PgpKeyPair
                  (
                        Program.ElGamalToPgpPublicKey((ElGamalPublicKeyParameters)guest.Public)
                      , Program.ElGamalToPgpPrivateKey
                        (
                              (ElGamalPublicKeyParameters)guest.Public
                            , (ElGamalPrivateKeyParameters)guest.Private
                        )
                  )
            );

            using (FileStream fspvk = File.Create(_private_key))
                using (Stream stm = armored ? (Stream)new ArmoredOutputStream(fspvk) : fspvk)
                    krg.GenerateSecretKeyRing().Encode(stm);

            using (FileStream fspbk = File.Create(_public_key))
                using (Stream stm = armored ? (Stream)new ArmoredOutputStream(fspbk) : fspbk)
                    krg.GeneratePublicKeyRing().Encode(stm);
        }

        //----------------------------------------------------------------------------------

        private static PgpPublicKey GetPgpPublicKey ()
        {
            using (Stream f = File.OpenRead(_public_key))
            {
                using (Stream i = PgpUtilities.GetDecoderStream(f))
                {
                    PgpPublicKeyRingBundle prb = new PgpPublicKeyRingBundle(i);

                    foreach (PgpPublicKeyRing pkr in prb.GetKeyRings())
                        foreach (PgpPublicKey pbk in pkr.GetPublicKeys())
                            if (pbk != null && pbk.IsEncryptionKey)
                                return pbk;
                }
            }

            throw new Exception(string.Format(MSG_NO_PGP_KEY_FOUND, "public"));
        }
        
        //----------------------------------------------------------------------------------

        private static PgpPrivateKey GetPgpPrivateKey (bool master = false)
        {
            Program.DefinePassword(true);

            using (Stream f = File.OpenRead(_private_key))
            {
                using (Stream i = PgpUtilities.GetDecoderStream(f))
                {
                    PgpSecretKeyRingBundle psr = new PgpSecretKeyRingBundle(i);

                    foreach (PgpSecretKeyRing skr in psr.GetKeyRings())
                    {
                        foreach (PgpSecretKey psk in skr.GetSecretKeys())
                        {
                            if (psk != null && psk.IsSigningKey) while (true)
                            {
                                try
                                {
                                    _hasprivatekey = true;
                                    PgpPrivateKey pvk = psk.ExtractPrivateKey(_password.ToCharArray());

                                    if (pvk.Key is DsaPrivateKeyParameters || pvk.Key is ECPrivateKeyParameters)
                                        if (!master) break;

                                    return pvk;
                                }

                                catch (PgpException e)
                                {
                                    if (!e.Message.StartsWith("Checksum mismatch"))
                                        throw e;

                                    else
                                    {
                                        if (_raisepwd)
                                            throw new Exception(MSG_INCORRECT_PASSWORD);

                                        Messenger.Print
                                        (
                                              Messenger.Icon.ERROR
                                            , MSG_INCORRECT_PASSWORD +
                                              MSG_PLEASE_TRY_AGAIN
                                            , false
                                            , true
                                        );

                                        Program.ExceptionControl(-2146233088);

                                        _password = string.Empty;
                                        Program.DefinePassword(true);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            throw new Exception(string.Format(MSG_NO_PGP_KEY_FOUND, "private"));
        }

        //----------------------------------------------------------------------------------

        private static PgpPublicKey GetPgpPublicKeyFromRsa (RSACryptoServiceProvider rsa)
        {
            RSAParameters p = rsa.ExportParameters(false);

            return new PgpPublicKey
            (
                  PublicKeyAlgorithmTag.RsaGeneral
                , (AsymmetricKeyParameter)new RsaKeyParameters
                  (
                        false
                      , new BigInteger(1, p.Modulus)
                      , new BigInteger(1, p.Exponent)
                  )
                , DateTime.Now
            );
        }
        
        //----------------------------------------------------------------------------------

        private static PgpPrivateKey GetPgpPrivateKeyFromRsa (RSACryptoServiceProvider rsa)
        {
            RSAParameters p = rsa.ExportParameters(true);

            return new PgpPrivateKey
            (
                  0
                , new PublicKeyPacket
                  (
                        PublicKeyAlgorithmTag.RsaGeneral
                      , DateTime.Now
                      , new RsaPublicBcpgKey
                        (
                              new BigInteger(1, p.Modulus)
                            , new BigInteger(1, p.Exponent)
                        )
                  )

                , new RsaPrivateCrtKeyParameters
                  (
                        new BigInteger(1, p.Modulus)
                      , new BigInteger(1, p.Exponent)
                      , new BigInteger(1, p.D)
                      , new BigInteger(1, p.P)
                      , new BigInteger(1, p.Q)
                      , new BigInteger(1, p.DP)
                      , new BigInteger(1, p.DQ)
                      , new BigInteger(1, p.InverseQ)
                  )
            );
        }
        
        //----------------------------------------------------------------------------------

        private static void PgpPublicKeyToRsa (PgpPublicKey pbk, RSACryptoServiceProvider rsa)
        {
            if (pbk.Algorithm == PublicKeyAlgorithmTag.RsaGeneral)
            {
                RsaKeyParameters k = (RsaKeyParameters)pbk.GetKey();
                RSAParameters    p = new RSAParameters();

                p.Modulus  = k.Modulus.ToByteArrayUnsigned();
                p.Exponent = k.Exponent.ToByteArrayUnsigned();

                rsa.ImportParameters(p);
            }

            else throw new Exception(MSG_INVALID_RSA_KEY);
        }
        
        //----------------------------------------------------------------------------------

        private static void PgpPrivateKeyToRsa (PgpPrivateKey pvk, RSACryptoServiceProvider rsa)
        {
            if (pvk.Key is RsaPrivateCrtKeyParameters)
            {
                RsaPrivateCrtKeyParameters k = (RsaPrivateCrtKeyParameters)pvk.Key;
                RSAParameters              p = new RSAParameters();

                p.Modulus  = k.Modulus.ToByteArrayUnsigned();
                p.Exponent = k.PublicExponent.ToByteArrayUnsigned();
                p.D        = k.Exponent.ToByteArrayUnsigned();
                p.P        = k.P.ToByteArrayUnsigned();
                p.Q        = k.Q.ToByteArrayUnsigned();
                p.DP       = k.DP.ToByteArrayUnsigned();
                p.DQ       = k.DQ.ToByteArrayUnsigned();
                p.InverseQ = k.QInv.ToByteArrayUnsigned();

                rsa.ImportParameters(p);
            }

            else throw new Exception(MSG_INVALID_RSA_KEY);
        }


        //----------------------------------------------------------------------------------

        private static ElGamalPublicKeyParameters PgpPublicKeyToElGamal (PgpPublicKey pbk)
        {
            if (pbk != null)
            {
                if (pbk.Algorithm == PublicKeyAlgorithmTag.ElGamalGeneral)
                    return (ElGamalPublicKeyParameters)pbk.GetKey();

                else throw new Exception(MSG_INVALID_ELGAMAL_KEY);
            }

            return null;
        }

        //----------------------------------------------------------------------------------

        private static ElGamalPrivateKeyParameters PgpPrivateKeyToElGamal (PgpPrivateKey pvk)
        {
            if (pvk != null)
            {
                if (pvk.Key is ElGamalPrivateKeyParameters)
                    return (ElGamalPrivateKeyParameters)pvk.Key;

                else throw new Exception(MSG_INVALID_ELGAMAL_KEY);
            }

            return null;
        }

        //----------------------------------------------------------------------------------

        private static void WriteAndSign 
        (
              Stream                src
            , Stream                dest
            , Stream                compressed
            , PgpSignatureGenerator psg
            , long                  srclen
        ){
            byte[] b = new byte[_buffersize];
            long n = 0;

            for (int c; (c = src.Read(b, 0, _buffersize)) > 0; )
            {
                dest.Write(b, 0, c);
                psg.Update(b, 0, c);
                Program.Progress(n += c, srclen, c);
            }

            Array.Clear(b, 0, b.Length);
            psg.Generate().Encode(compressed);

            if (_percent < 100)
                Program.Progress(srclen, srclen, 0);
        }

        //----------------------------------------------------------------------------------

        private static void PgpEncrypt 
        (
              PgpPublicKey pbk
            , Stream       src
            , Stream       dest
            , string       name
            , bool         armoed
            , bool         check
        ){
            byte[]                     ebf = new byte[_buffersize];
            byte[]                     lbf = new byte[_buffersize];
            PgpLiteralDataGenerator    ldg = new PgpLiteralDataGenerator();
            PgpCompressedDataGenerator cdg = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);
            PgpEncryptedDataGenerator  edg = new PgpEncryptedDataGenerator(_ska, check, new SecureRandom());
            PgpSignatureGenerator      psg = null;

            edg.AddMethod(pbk);
            using (Stream os = armoed ? new ArmoredOutputStream(dest) : dest)
            {
                using (Stream es = edg.Open(os, ebf))
                {
                    using (Stream cs = cdg.Open(es))
                    {
                        if (_pgp_sign)
                        {
                            if (_pgp_pvk == null)
                                throw new Exception(MSG_INVALID_PRIVATE_KEY);

                            psg = new PgpSignatureGenerator(_pgp_pvk.PublicKeyPacket.Algorithm, HashAlgorithmTag.Sha1);
                            psg.InitSign(PgpSignature.BinaryDocument, _pgp_pvk);

                            foreach (string uid in pbk.GetUserIds())
                            {
                                PgpSignatureSubpacketGenerator ssg = new PgpSignatureSubpacketGenerator();

                                ssg.SetSignerUserId(false, uid);
                                psg.SetHashedSubpackets(ssg.Generate());
                                break;
                            }

                            psg.GenerateOnePassVersion(false).Encode(cs);
                        }

                        using (Stream ls = ldg.Open(cs, PgpLiteralData.Binary, name, DateTime.Now, lbf))
                        {
                            if (_pgp_sign)
                                Program.WriteAndSign(src, ls, cs, psg, src.Length);

                            else Program.Write(src, ls, src.Length);

                            ldg.Close();
                            cdg.Close();
                            edg.Close();
                        }
                    }
                }
            }

            Array.Clear(ebf, 0, ebf.Length);
            Array.Clear(lbf, 0, lbf.Length);
        }

		//----------------------------------------------------------------------------------

        private static void PgpDecrypt
        (
              PgpPrivateKey pvk
            , Stream        src
            , Stream        dest
        ){
            using (Stream sis = PgpUtilities.GetDecoderStream(src))
            {
                PgpObjectFactory     of = new PgpObjectFactory(sis);
                PgpObject            po = null;
                PgpEncryptedDataList ed = null;
                byte                 nf = 1;

                while (ed == null && (po = of.NextPgpObject()) != null)
                    if (po is PgpEncryptedDataList)
                        ed = (PgpEncryptedDataList)po;

                if (ed == null || ed.IsEmpty)
                    throw new Exception("No Pgp data found!");

                foreach (PgpPublicKeyEncryptedData pd in ed.GetEncryptedDataObjects()) if (pd != null)
                {
                    PgpLiteralData ld = null;
                    using (Stream ds = pd.GetDataStream(pvk))
                    {
                        of = new PgpObjectFactory(ds);
                        if ((po = of.NextPgpObject()) is PgpCompressedData)
                        {
                            using (Stream tmp = ((PgpCompressedData)po).GetDataStream())
                            {
                                of = new PgpObjectFactory(tmp);
                                if ((po = of.NextPgpObject()) is PgpOnePassSignatureList)
                                     ld = (PgpLiteralData)of.NextPgpObject();

                                else ld = (PgpLiteralData)po;
                            }

                            nf = 2;
                        }

                        else if (po is PgpLiteralData)
                            ld = (PgpLiteralData)po;

                        if (ld == null)
                            throw new Exception("Pgp data type unknown!");

                        using (Stream so = ld.GetInputStream())
                            Program.Write(so, dest, src.Length * nf);
                    }

                    if (pd.IsIntegrityProtected() && !pd.Verify())
                        throw new Exception("Pgp data integrity check fails!");

                    return;
                }
            }
        }

        //----------------------------------------------------------------------------------

        private static void Write (BufferedBlockCipher bc, Stream src, Stream dest)
        {
            byte[] i = new byte[_buffersize];
            byte[] o = new byte[bc.GetBlockSize() + bc.GetOutputSize(_buffersize)];
            long   l = src.Length;
            long   p = 0;
            int    n;

            while ((n = src.Read(i, 0, i.Length)) > 0)
            {
                dest.Write(o, 0, bc.ProcessBytes(i, 0, n, o, 0));
                Program.Progress(p += n, l, n);
            }

            if ((n = bc.DoFinal(o, 0)) > 0)
                dest.Write(o, 0, n);

            Array.Clear(i, 0, i.Length);
            Array.Clear(o, 0, o.Length);
        }

        //----------------------------------------------------------------------------------

        private static void CamelliaCrypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(new CamelliaEngine())
                , Program.GetBouncyCastlePadding()
            );

            bc.Init(encryption, new KeyParameter(_sk.key));
            Program.Write(bc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void SerpentCrypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(new SerpentEngine())
                , Program.GetBouncyCastlePadding()
            );

            bc.Init(encryption, new KeyParameter(_sk.key));
            Program.Write(bc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void TnepresCrypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(new TnepresEngine())
                , Program.GetBouncyCastlePadding()
            );

            bc.Init(encryption, new KeyParameter(_sk.key));
            Program.Write(bc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void TwofishCrypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(new TwofishEngine())
                , Program.GetBouncyCastlePadding()
            );

            bc.Init(encryption, new KeyParameter(_sk.key));
            Program.Write(bc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void BlowfishCrypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(new BlowfishEngine())
                , Program.GetBouncyCastlePadding()
            );

            bc.Init(encryption, new KeyParameter(_sk.key));
            Program.Write(bc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void ThreefishCrypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(new ThreefishEngine(_keysize))
                , Program.GetBouncyCastlePadding()
            );

            ICipherParameters cp;

            if (_without_iv)
                 cp = new KeyParameter(_sk.key);

            else cp = new TweakableBlockCipherParameters(new KeyParameter(_sk.key), _sk.iv);

            bc.Init(encryption, cp);
            Program.Write(bc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void Cast5Crypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(new Cast5Engine())
                , Program.GetBouncyCastlePadding()
            );

            bc.Init(encryption, new KeyParameter(_sk.key));
            Program.Write(bc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void Cast6Crypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(new Cast6Engine())
                , Program.GetBouncyCastlePadding()
            );

            bc.Init(encryption, new KeyParameter(_sk.key));
            Program.Write(bc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void IdeaCrypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(new IdeaEngine())
                , Program.GetBouncyCastlePadding()
            );

            bc.Init(encryption, new KeyParameter(_sk.key));
            Program.Write(bc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void NoekeonCrypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(new NoekeonEngine())
                , Program.GetBouncyCastlePadding()
            );

            bc.Init(encryption, new KeyParameter(_sk.key));
            Program.Write(bc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void SeedCrypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(new SeedEngine())
                , Program.GetBouncyCastlePadding()
            );

            bc.Init(encryption, new KeyParameter(_sk.key));
            Program.Write(bc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void GostCrypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(new Gost28147Engine())
                , Program.GetBouncyCastlePadding()
            );

            if (string.IsNullOrEmpty(_sbox))
                bc.Init(encryption, new KeyParameter(_sk.key));

            else bc.Init
            (
                  encryption
                , new ParametersWithSBox
                  (
                        new KeyParameter(_sk.key)
                      , _sk.iv != null ? _sk.iv : Gost28147Engine.GetSBox(_sbox)
                  )
            );

            Program.Write(bc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void TeaCrypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(new TeaEngine())
                , Program.GetBouncyCastlePadding()
            );

            bc.Init(encryption, new KeyParameter(_sk.key));
            Program.Write(bc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void XTeaCrypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(new XteaEngine())
                , Program.GetBouncyCastlePadding()
            );

            bc.Init(encryption, new KeyParameter(_sk.key));
            Program.Write(bc, src, dest);
        }
        
        //----------------------------------------------------------------------------------

        private static void SkipjackCrypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(new SkipjackEngine())
                , Program.GetBouncyCastlePadding()
            );

            bc.Init(encryption, new KeyParameter(_sk.key));
            Program.Write(bc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void RC5Crypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(_rc5b64 ? (IBlockCipher)new RC564Engine() : new RC532Engine())
                , Program.GetBouncyCastlePadding()
            );

            bc.Init(encryption, new RC5Parameters(_sk.key, _rounds));
            Program.Write(bc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void RC6Crypt (bool encryption, Stream src, Stream dest)
        {
            BufferedBlockCipher bc = new PaddedBufferedBlockCipher
            (
                  Program.GetBlockCipherMode(new RC6Engine())
                , Program.GetBouncyCastlePadding()
            );

            bc.Init(encryption, new KeyParameter(_sk.key));
            Program.Write(bc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void Write (IStreamCipher sc, Stream src, Stream dest)
        {
            byte[] i = new byte[_buffersize];
            byte[] o = new byte[_buffersize];
            long   l = src.Length;
            long   p = 0;

            for (int n; (n = src.Read(i, 0, i.Length)) > 0; )
            {
                sc.ProcessBytes(i, 0, n, o, 0);
                dest.Write(o, 0, n);
                Program.Progress(p += n, l, n);
            }

            Array.Clear(i, 0, i.Length);
            Array.Clear(o, 0, o.Length);
        }

        //----------------------------------------------------------------------------------

        private static void RC4Crypt (bool encryption, Stream src, Stream dest)
        {
            RC4Engine rc4 = new RC4Engine();

            rc4.Init(encryption, new KeyParameter(_sk.key));
            Program.Write(rc4, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void IsaacCrypt (bool encryption, Stream src, Stream dest)
        {
            IsaacEngine ie = new IsaacEngine();

            ie.Init(encryption, new KeyParameter(_sk.key));
            Program.Write(ie, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void HongjunCrypt (bool encryption, Stream src, Stream dest)
        {
            IStreamCipher hc;

            switch (_keysize)
            {
                case 128:
                    hc = new HC128Engine();
                    break;

                case 256:
                    hc = new HC256Engine();
                    break;

                default:
                    throw new Exception(MSG_INVALID_KEY_SIZE);
            }

            hc.Init(encryption, new ParametersWithIV(new KeyParameter(_sk.key), _sk.iv));
            Program.Write(hc, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void Salsa20Crypt (bool encryption, Stream src, Stream dest)
        {
            Salsa20Engine se = new Salsa20Engine(_rounds);

            se.Init(encryption, new ParametersWithIV(new KeyParameter(_sk.key), _sk.iv));
            Program.Write(se, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void XSalsa20Crypt (bool encryption, Stream src, Stream dest)
        {
            XSalsa20Engine se = new XSalsa20Engine();

            se.Init(encryption, new ParametersWithIV(new KeyParameter(_sk.key), _sk.iv));
            Program.Write(se, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void ChaChaCrypt (bool encryption, Stream src, Stream dest)
        {
            ChaChaEngine se = new ChaChaEngine(_rounds);

            se.Init(encryption, new ParametersWithIV(new KeyParameter(_sk.key), _sk.iv));
            Program.Write(se, src, dest);
        }

        //---------------------------------------------------------------------------------

        private static void VmpcCrypt (bool encryption, Stream src, Stream dest)
        {
            VmpcEngine ve = _ksa3 ? new VmpcKsa3Engine() : new VmpcEngine();

            ve.Init(encryption, new ParametersWithIV(new KeyParameter(_sk.key), _sk.iv));
            Program.Write(ve, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void Write (BufferedCipherBase bcb, int buffersize, Stream src, Stream dest)
        {
            byte[] i = new byte[buffersize];
            long   l = src.Length;
            long   p = 0;
            int    n;

            while ((n = src.Read(i, 0, i.Length)) > 0)
            {
                byte[] o = bcb.DoFinal(i, 0, n);

                dest.Write(o, 0, o.Length);
                Array.Clear(o, 0, o.Length);
                Program.Progress(p += n, l, n);
            }

            Array.Clear(i, 0, i.Length);
        }

        //----------------------------------------------------------------------------------

        private static void ValidateKeyPairSize ()
        {
            if (_keysize < 128 || _keysize % 8 != 0)
                throw new Exception(MSG_INVALID_KEY_SIZE);

            else if (_keysize < 768) Program.Question
            (
                  MSG_KEYPAIR_INSECURE + MSG_CONTINUE_QUESTION
                , true
            );

            else if (_keysize > 1024) Program.Question
            (
                  MSG_LARGE_KEYSIZE + MSG_CONTINUE_QUESTION
                , true
            );
        }

        //----------------------------------------------------------------------------------

        private static AsymmetricCipherKeyPair ElGamalKeyPairGen 
        (
              bool                        save = true
            , ElGamalPublicKeyParameters  pbk  = null
            , ElGamalPrivateKeyParameters pvk  = null

        ){
            AsymmetricCipherKeyPair akp = null;

            if (pbk != null || pvk != null)
                Program.ValidateKeyPairFiles(pbk != null, pvk != null);

            else
            {
                if (save)
                    Program.ValidateKeyPairFiles();

                Program.ValidateKeyPairSize();

                ElGamalKeyPairGenerator    kpg = new ElGamalKeyPairGenerator();
                ElGamalParametersGenerator epg = new ElGamalParametersGenerator();

                epg.Init(_keysize, 8, new SecureRandom());
                kpg.Init
                (
                    new ElGamalKeyGenerationParameters
                    (
                          new SecureRandom()
                        , epg.GenerateParameters()
                    )
                );

                akp = kpg.GenerateKeyPair();
                pbk = (ElGamalPublicKeyParameters)akp.Public;
                pvk = (ElGamalPrivateKeyParameters)akp.Private;
            }

            if (save)
            {
                XmlSerializer xml = new XmlSerializer(typeof(ElGamalKey));
                ElGamalKey    egk;

                if (pbk != null)
                {
                    egk.g = pbk.Parameters.G.ToByteArray();
                    egk.p = pbk.Parameters.P.ToByteArray();
                    egk.l = pbk.Parameters.L;
                    egk.n = pbk.Y.ToByteArray();
                    egk.b = pbk.IsPrivate;

                    using (FileStream fs = File.Create(_public_key))
                        xml.Serialize(fs, egk);

                    Array.Clear(egk.g, 0, egk.g.Length);
                    Array.Clear(egk.p, 0, egk.p.Length);
                    Array.Clear(egk.n, 0, egk.n.Length);
                }

                if (pvk != null)
                {
                    egk.g = pvk.Parameters.G.ToByteArray();
                    egk.p = pvk.Parameters.P.ToByteArray();
                    egk.l = pvk.Parameters.L;
                    egk.n = pvk.X.ToByteArray();
                    egk.b = pvk.IsPrivate;

                    using (FileStream fs = File.Create(_private_key))
                        xml.Serialize(fs, egk);

                    Array.Clear(egk.g, 0, egk.g.Length);
                    Array.Clear(egk.p, 0, egk.p.Length);
                    Array.Clear(egk.n, 0, egk.n.Length);
                }
            }

            return akp;
        }

        //----------------------------------------------------------------------------------

        private static ElGamalKeyParameters ElGamalImportKey (string path)
        {
            ElGamalKeyParameters key;
            ElGamalKey           egk;
            XmlSerializer        xml = new XmlSerializer(typeof(ElGamalKey));

            using (FileStream fs = File.OpenRead(path))
                egk = (ElGamalKey)xml.Deserialize(fs);

            ElGamalParameters egp = new ElGamalParameters
            (
                  new BigInteger(egk.p)
                , new BigInteger(egk.g)
                , egk.l
            );

            if (egk.b) key = new ElGamalPrivateKeyParameters
            (
                  new BigInteger(egk.n)
                , egp
            );

            else key = new ElGamalPublicKeyParameters
            (
                  new BigInteger(egk.n)
                , egp
            );

            Array.Clear(egk.g, 0, egk.g.Length);
            Array.Clear(egk.p, 0, egk.p.Length);
            Array.Clear(egk.n, 0, egk.n.Length);
            
            return key;
        }

        //----------------------------------------------------------------------------------

        private static AsymmetricCipherKeyPair ElGamalImportKeyPair ()
        {
            if (!File.Exists(_public_key))
                throw new Exception(MSG_INVALID_PUBLIC_KEY);

            if (!File.Exists(_private_key))
                throw new Exception(MSG_INVALID_PRIVATE_KEY);
            
            ElGamalPublicKeyParameters  pbk = null;
            ElGamalPrivateKeyParameters pvk = null;
            ElGamalKeyParameters        ekp = Program.ElGamalImportKey(_public_key);

            if (ekp is ElGamalPublicKeyParameters)
                pbk = (ElGamalPublicKeyParameters)ekp;

            else throw new Exception(MSG_INVALID_PUBLIC_KEY);

            ekp = Program.ElGamalImportKey(_private_key);

            if (ekp is ElGamalPrivateKeyParameters)
                pvk = (ElGamalPrivateKeyParameters)ekp;

            else throw new Exception(MSG_INVALID_PRIVATE_KEY);

            return new AsymmetricCipherKeyPair(pbk, pvk);
        }

        //----------------------------------------------------------------------------------

        private static OaepEncoding GetOaepEncoding 
        (
              IAsymmetricBlockCipher engine
            , int                    bits
        ){
            switch (_hash)
            {
                case HASH_SHA512:
                    if (bits < 1048) throw new Exception
                    (
                        string.Format
                        (
                              MSG_INVALID_HASH_KEY_SIZE
                            , HASH_SHA512
                            , 1048
                        )
                    );

                    return new OaepEncoding(engine, new Sha512Digest());

                case HASH_SHA384:
                    if (bits < 792) throw new Exception
                    (
                        string.Format
                        (
                            MSG_INVALID_HASH_KEY_SIZE
                            , HASH_SHA512
                            , 792
                        )
                    );

                    return new OaepEncoding(engine, new Sha384Digest());

                case HASH_SHA256:
                    if (bits < 536) throw new Exception
                    (
                        string.Format
                        (
                              MSG_INVALID_HASH_KEY_SIZE
                            , HASH_SHA512
                            , 536
                        )
                    );

                    return new OaepEncoding(engine, new Sha256Digest());

                case HASH_SHA224:
                    if (bits < 472) throw new Exception
                    (
                        string.Format
                        (
                              MSG_INVALID_HASH_KEY_SIZE
                            , HASH_SHA512
                            , 472
                        )
                    );

                    return new OaepEncoding(engine, new Sha224Digest());

                case HASH_SHA1:
                    if (bits < 344) throw new Exception
                    (
                        string.Format
                        (
                              MSG_INVALID_HASH_KEY_SIZE
                            , HASH_SHA512
                            , 344
                        )
                    );

                    return new OaepEncoding(engine, new Sha1Digest());

                case HASH_MD5:
                    if (bits < 280) throw new Exception
                    (
                        string.Format
                        (
                              MSG_INVALID_HASH_KEY_SIZE
                            , HASH_SHA512
                            , 280
                        )
                    );

                    return new OaepEncoding(engine, new MD5Digest());

                default:
                    throw new Exception(MSG_INVALID_HASH);
            }
        }

        //----------------------------------------------------------------------------------
        
        private static void ElGamalCrypt
        (
              bool                 encryption
            , ElGamalKeyParameters key
            , Stream               src
            , Stream               dest
        ){
            IAsymmetricBlockCipher abc;

            if (_padding == CryptPadding.OAEP)
                abc = Program.GetOaepEncoding(new ElGamalEngine(), key.Parameters.P.BitLength);

            else if (_padding == CryptPadding.PKCS1)
                abc = new Pkcs1Encoding(new ElGamalEngine());

            else throw new Exception(MSG_INVALID_PADDING_MODE);

            BufferedAsymmetricBlockCipher bac = new BufferedAsymmetricBlockCipher(abc);

            bac.Init(encryption, key);
            Program.Write(bac, bac.GetBlockSize(), src, dest);
        }

        //----------------------------------------------------------------------------------

        private static PgpPublicKey ElGamalToPgpPublicKey (ElGamalPublicKeyParameters pbk)
        {
            return new PgpPublicKey
            (
                  PublicKeyAlgorithmTag.ElGamalGeneral
                , pbk
                , DateTime.Now
            );
        }

        //----------------------------------------------------------------------------------

        private static PgpPrivateKey ElGamalToPgpPrivateKey 
        (
              ElGamalPublicKeyParameters  pbk
            , ElGamalPrivateKeyParameters pvk
        ){
            return new PgpPrivateKey
            (
                  0
                , new PublicKeyPacket
                  (
                        PublicKeyAlgorithmTag.ElGamalGeneral
                      , DateTime.Now
                      , new ElGamalPublicBcpgKey
                        (
                              pbk.Parameters.P
                            , pbk.Parameters.G
                            , pbk.Y
                        )
                  )
                , pvk
            );
        }
        
        //----------------------------------------------------------------------------------

        private static void NaccacheSternKeyPairGen ()
        {
            Program.ValidateKeyPairSize();
            Program.ValidateKeyPairFiles();

            NaccacheSternKeyPairGenerator        kpg = new NaccacheSternKeyPairGenerator();
            NaccacheSternKeyGenerationParameters kgp = new NaccacheSternKeyGenerationParameters
            (
                  new SecureRandom()
                , _keysize
                , 8
                , 30
            );

            kpg.Init(kgp);

            AsymmetricCipherKeyPair           akp = kpg.GenerateKeyPair();
            NaccacheSternKeyParameters        pbk = (NaccacheSternKeyParameters)akp.Public;
            NaccacheSternPrivateKeyParameters pvk = (NaccacheSternPrivateKeyParameters)akp.Private;
            NaccacheSternKey                  nsk;

            nsk.g = pbk.G.ToByteArray();
            nsk.n = pbk.Modulus.ToByteArray();
            nsk.l = pbk.LowerSigmaBound;
            nsk.p = null;
            nsk.s = null;
            nsk.b = pbk.IsPrivate;

            XmlSerializer xml = new XmlSerializer(typeof(NaccacheSternKey));

            using (FileStream fs = File.Create(_public_key))
                xml.Serialize(fs, nsk);

            int l = pvk.SmallPrimesList.Count;
            nsk.p = pvk.PhiN.ToByteArray();
            nsk.b = pvk.IsPrivate;
            nsk.s = new byte[l][];

            for (int i = 0; i < l; ++i)
                nsk.s[i] = ((BigInteger)pvk.SmallPrimesList[i]).ToByteArray();

            using (FileStream fs = File.Create(_private_key))
                xml.Serialize(fs, nsk);

            for (int i = 0; i < l; ++i)
                Array.Clear(nsk.s[i], 0, nsk.s[i].Length);

            Array.Clear(nsk.s, 0, nsk.s.Length);
            Array.Clear(nsk.p, 0, nsk.p.Length);
            Array.Clear(nsk.g, 0, nsk.g.Length);
            Array.Clear(nsk.n, 0, nsk.n.Length);
        }

        //----------------------------------------------------------------------------------

        private static NaccacheSternKeyParameters NaccacheSternImportKey (string path)
        {
            NaccacheSternKeyParameters key;
            NaccacheSternKey           nsk;
            XmlSerializer              xml = new XmlSerializer(typeof(NaccacheSternKey));

            using (FileStream fs = File.OpenRead(path))
                nsk = (NaccacheSternKey)xml.Deserialize(fs);

            if (!nsk.b) key = new NaccacheSternKeyParameters
            (
                  nsk.b
                , new BigInteger(nsk.g)
                , new BigInteger(nsk.n)
                , nsk.l
            );

            else
            {
                int              n = nsk.s.Length;
                List<BigInteger> l = new List<BigInteger>(nsk.s.Length);

                for (int i = 0; i < n; ++i)
                {
                    l.Add(new BigInteger(nsk.s[i]));
                    Array.Clear(nsk.s[i], 0, nsk.s[i].Length);
                }

                key = new NaccacheSternPrivateKeyParameters
                (
                      new BigInteger(nsk.g)
                    , new BigInteger(nsk.n)
                    , nsk.l
                    , l
                    , new BigInteger(nsk.p)
                );

                Array.Clear(nsk.p, 0, nsk.p.Length);
                Array.Clear(nsk.s, 0, nsk.s.Length);
            }

            Array.Clear(nsk.g, 0, nsk.g.Length);
            Array.Clear(nsk.n, 0, nsk.n.Length);

            return key;
        }

        //----------------------------------------------------------------------------------

        private static void NaccacheSternCrypt
        (
              bool                       encryption
            , NaccacheSternKeyParameters key
            , Stream                     src
            , Stream                     dest
        ){
            BufferedAsymmetricBlockCipher bac = new BufferedAsymmetricBlockCipher
            (
                new Pkcs1Encoding(new NaccacheSternEngine())
            );

            bac.Init(encryption, key);
            Program.Write(bac, bac.GetBlockSize(), src, dest);
        }

        //----------------------------------------------------------------------------------

        private static void ClearEciesKey (EciesKey eck)
        {
            Array.Clear(eck.n, 0, eck.n.Length);
            Array.Clear(eck.h, 0, eck.h.Length);
            Array.Clear(eck.g, 0, eck.g.Length);

            if (eck.c  != null) Array.Clear(eck.c, 0, eck.c.Length);
            if (eck.s  != null) Array.Clear(eck.s, 0, eck.s.Length);
            if (eck.q  != null) Array.Clear(eck.q, 0, eck.q.Length);
            if (eck.d  != null) Array.Clear(eck.d, 0, eck.d.Length);
            if (eck.ca != null) Array.Clear(eck.ca, 0, eck.ca.Length);
            if (eck.cb != null) Array.Clear(eck.cb, 0, eck.cb.Length);
            if (eck.co != null) Array.Clear(eck.co, 0, eck.co.Length);
            if (eck.ch != null) Array.Clear(eck.ch, 0, eck.ch.Length);
            if (eck.cq != null) Array.Clear(eck.cq, 0, eck.cq.Length);
        }

        //----------------------------------------------------------------------------------

        private static AsymmetricCipherKeyPair GetCurveKeyPair ()
        {
            X9ECParameters      x9p = null;
            ECDomainParameters  edp = null;


            switch (_curvestore)
            {
                case CUSTOM:
                    x9p = CustomNamedCurves.GetByName(_curve);
                    break;

                case ANSSI:
                    x9p = AnssiNamedCurves.GetByName(_curve);
                    break;

                case TELETRUST:
                    x9p = TeleTrusTNamedCurves.GetByName(_curve);
                    break;

                case NIST:
                    x9p = NistNamedCurves.GetByName(_curve);
                    break;

                case SEC:
                    x9p = SecNamedCurves.GetByName(_curve);
                    break;

                case X962:
                    x9p = X962NamedCurves.GetByName(_curve);
                    break;

                case GOST:
                    edp = ECGost3410NamedCurves.GetByName(_curve);
                    break;

                default:
                    throw new Exception(MSG_INVALID_CURVE_STORE);
            }

            if (x9p != null)
                edp = new ECDomainParameters(x9p.Curve, x9p.G, x9p.N, x9p.H, x9p.GetSeed());

            else if (edp == null)
                throw new Exception("Curve not found!");

            ECKeyPairGenerator      kpg = new ECKeyPairGenerator();
            KeyGenerationParameters kgp = new ECKeyGenerationParameters(edp, new SecureRandom());

            kpg.Init(kgp);
            return kpg.GenerateKeyPair();
        }

        //----------------------------------------------------------------------------------

        private static void EciesKeyPairGen ()
        {
            Program.ValidateKeyPairFiles();

            AsymmetricCipherKeyPair akp = Program.GetCurveKeyPair();
            ECPrivateKeyParameters  pvk = (ECPrivateKeyParameters)akp.Private;
            ECPublicKeyParameters   pbk = (ECPublicKeyParameters)akp.Public;
            XmlSerializer           xml = new XmlSerializer(typeof(EciesKey));
            EciesKey                eck;
            ECDomainParameters      edp;

            string f = _public_key;
            byte   n = 0;
            
            do
            {
                edp = (eck.b = n > 0) ? pvk.Parameters : pbk.Parameters;

                if (eck.b)
                {
                    eck.d = pvk.D.ToByteArray();
                    eck.q = null;
                }

                else 
                {
                    eck.d = null;
                    eck.q = pbk.Q.GetEncoded();
                }

                eck.c = null;
                eck.n = edp.N.ToByteArray();
                eck.h = edp.H.ToByteArray();
                eck.s = edp.GetSeed();
                eck.g = edp.G.GetEncoded();

                if (edp.Curve is FpCurve)
                {
                    FpCurve c1 = (FpCurve)edp.Curve;

                    eck.cq  = c1.Q.ToByteArray();
                    eck.ca  = c1.A.ToBigInteger().ToByteArray();
                    eck.cb  = c1.B.ToBigInteger().ToByteArray();
                    eck.co  = c1.Order.ToByteArray();
                    eck.ch  = c1.Cofactor.ToByteArray();
                    eck.cm  = eck.ck1 = eck.ck2 = eck.ck3 = 0;
                }

                else if (edp.Curve is F2mCurve)
                {
                    F2mCurve c2 = (F2mCurve)edp.Curve;

                    eck.cq  = null;
                    eck.ca  = c2.A.ToBigInteger().ToByteArray();
                    eck.cb  = c2.B.ToBigInteger().ToByteArray();
                    eck.co  = c2.Order.ToByteArray();
                    eck.ch  = c2.Cofactor.ToByteArray();
                    eck.cm  = c2.M;
                    eck.ck1 = c2.K1;
                    eck.ck2 = c2.K2;
                    eck.ck3 = c2.K3;
                }

                else 
                {
                    eck.c  = Encoding.ASCII.GetBytes(edp.Curve.GetType().ToString());
                    eck.cq = eck.ca = eck.cb = eck.co = eck.ch = null;
                    eck.cm = eck.ck1 = eck.ck2 = eck.ck3 = 0;
                }

                using (FileStream fs = File.Create(f))
                    xml.Serialize(fs, eck);

                if (eck.cq != null)
                    Array.Clear(eck.cq, 0, eck.cq.Length);

                Program.ClearEciesKey(eck);

                f = _private_key;
            }

            while (++n < 2);
        }

        //----------------------------------------------------------------------------------

        private static void EciesDefParams 
        (
              EciesKey               eck
            , ref ECCurve            ecc
            , ref ECDomainParameters edp
        ){
            if (eck.c != null) ecc = (ECCurve)Activator.CreateInstance
            (
                Type.GetType(Encoding.UTF8.GetString(eck.c) + "," + 
                Assembly.GetExecutingAssembly().GetName().Name)
            );

            else if (eck.cm + eck.ck1 + eck.ck2 + eck.ck3 == 0) ecc = new FpCurve
            (
                  new BigInteger(eck.cq)
                , new BigInteger(eck.ca)
                , new BigInteger(eck.cb)
                , new BigInteger(eck.co)
                , new BigInteger(eck.ch)
            );

            else ecc = new F2mCurve
            (
                  eck.cm
                , eck.ck1
                , eck.ck2
                , eck.ck3
                , new BigInteger(eck.ca)
                , new BigInteger(eck.cb)
                , new BigInteger(eck.co)
                , new BigInteger(eck.ch)
            );

            edp = new ECDomainParameters
            (
                  ecc
                , ecc.DecodePoint(eck.g)
                , new BigInteger(eck.n)
                , new BigInteger(eck.h)
                , eck.s
            );
        }

        //----------------------------------------------------------------------------------

        private static void EciesImportKeys (ref ICipherParameters pbk, ref ICipherParameters pvk)
        {
            ECDomainParameters edp = null;
            ECCurve            ecc = null;
            XmlSerializer      xml = new XmlSerializer(typeof(EciesKey));
            EciesKey           eck;

            if (!File.Exists(_public_key))
                throw new Exception(MSG_INVALID_PUBLIC_KEY);

            using (FileStream fs = File.OpenRead(_public_key))
                eck = (EciesKey)xml.Deserialize(fs);

            if (eck.b || eck.q == null)
                throw new Exception(MSG_INVALID_PUBLIC_KEY);

            Program.EciesDefParams(eck, ref ecc, ref edp);

            pbk = new ECPublicKeyParameters(ecc.DecodePoint(eck.q), edp);
            Program.ClearEciesKey(eck);

            if (!File.Exists(_private_key))
                throw new Exception(MSG_INVALID_PRIVATE_KEY);

            using (FileStream fs = File.OpenRead(_private_key))
                eck = (EciesKey)xml.Deserialize(fs);

            if (!eck.b || eck.d == null)
                throw new Exception(MSG_INVALID_PRIVATE_KEY);

            Program.EciesDefParams(eck, ref ecc, ref edp);

            pvk = new ECPrivateKeyParameters(new BigInteger(eck.d), edp);
            Program.ClearEciesKey(eck);
        }

        //----------------------------------------------------------------------------------

        private static void DisplayCurveNames ()
        {
            Program.ShowBanner();

            IEnumerable e;

            switch (_curvestore)
            {
                case CUSTOM:
                    e = CustomNamedCurves.Names;
                    break;

                case ANSSI:
                    e = AnssiNamedCurves.Names;
                    break;

                case TELETRUST:
                    e = TeleTrusTNamedCurves.Names;
                    break;

                case NIST:
                    e = NistNamedCurves.Names;
                    break;

                case SEC:
                    e = SecNamedCurves.Names;
                    break;

                case X962:
                    e = X962NamedCurves.Names;
                    break;

                case GOST:
                    e = ECGost3410NamedCurves.Names;
                    break;

                default:
                    throw new Exception(MSG_INVALID_CURVE_STORE);
            }

            string t;
            string s = string.Empty;
            int    l = 0;

            foreach (string n in e)
                if (l < n.Length)
                    l = n.Length;

            byte  b = (byte)(80 / (l < 6 ? l + 4 : l > 8 && l < 12 ? l - 2 : l > 24 ? l - 22 : l));
            byte  x = b;
            byte  y = (byte)(l > 24 ? 1 : 3);
            byte  z = (byte)(y - 1);
            short m = y;

            s += '\n';
            l += ((80 - l) / l) + (l > 24 ? 4 : 0);

            foreach (string n in e)
            {
                if (--m == z)
                {
                    while (--x > 0)
                        s += ' ';

                    x = b;
                }

                t = n;
                while (t.Length < l)
                    t += ' ';

                s += t;

                if (m < 0)
                {
                    m = y;
                    s += '\n';
                    s += '\n';
                }
            }

            Console.WriteLine(s);
        }

        //----------------------------------------------------------------------------------

        private static void ClearDliesKey (DliesKey dlk)
        {
            Array.Clear(dlk.a, 0, dlk.a.Length);
            Array.Clear(dlk.g, 0, dlk.g.Length);
            Array.Clear(dlk.j, 0, dlk.j.Length);
            Array.Clear(dlk.p, 0, dlk.p.Length);
            Array.Clear(dlk.q, 0, dlk.q.Length);
            
            if (dlk.s != null)
                Array.Clear(dlk.s, 0, dlk.s.Length);

            if (!dlk.b) Array.Clear(dlk.y, 0, dlk.y.Length);
            else        Array.Clear(dlk.x, 0, dlk.x.Length);
        }

        //----------------------------------------------------------------------------------

        private static void DliesKeyPairGen ()
        {
            Program.ValidateKeyPairFiles();

            DHKeyPairGenerator    kpg = new DHKeyPairGenerator();
            DHParametersGenerator dpg = new DHParametersGenerator();

            dpg.Init(_keysize, 8, new SecureRandom());

            DHKeyGenerationParameters kgp = new DHKeyGenerationParameters
            (
                  new SecureRandom()
                , dpg.GenerateParameters()
            );

            kpg.Init(kgp);

            AsymmetricCipherKeyPair akp = kpg.GenerateKeyPair();
            DHPrivateKeyParameters  pvk = (DHPrivateKeyParameters)akp.Private;
            DHPublicKeyParameters   pbk = (DHPublicKeyParameters)akp.Public;
            XmlSerializer           xml = new XmlSerializer(typeof(DliesKey));
            DliesKey                dlk;

            string f = _public_key;
            byte   n = 0;

            do
            {
                DHParameters dhp = (dlk.b = n > 0) ? pvk.Parameters : pbk.Parameters;

                if (dlk.b)
                {
                    dlk.a = pvk.AlgorithmOid.GetDerEncoded();
                    dlk.x = pvk.X.ToByteArray();
                    dlk.y = null;
                }

                else
                {
                    dlk.a = pvk.AlgorithmOid.GetDerEncoded();
                    dlk.y = pbk.Y.ToByteArray();
                    dlk.x = null;
                }

                dlk.g = dhp.G.ToByteArray();
                dlk.j = dhp.J.ToByteArray();
                dlk.l = dhp.L;
                dlk.m = dhp.M;
                dlk.p = dhp.P.ToByteArray();
                dlk.q = dhp.Q.ToByteArray();

                if (dhp.ValidationParameters != null)
                {
                    dlk.s = dhp.ValidationParameters.GetSeed();
                    dlk.c = dhp.ValidationParameters.Counter;
                }

                else
                {
                    dlk.s = null;
                    dlk.c = 0;
                }

                using (FileStream fs = File.Create(f))
                    xml.Serialize(fs, dlk);

                Program.ClearDliesKey(dlk);
                f = _private_key;
            }
            while (++n < 2);
        }

        //----------------------------------------------------------------------------------

        private static void DliesImportKeys (ref ICipherParameters pbk, ref ICipherParameters pvk)
        {
            XmlSerializer xml = new XmlSerializer(typeof(DliesKey));
            DliesKey      dlk;

            if (!File.Exists(_public_key))
                throw new Exception(MSG_INVALID_PUBLIC_KEY);

            using (FileStream fs = File.OpenRead(_public_key))
                dlk = (DliesKey)xml.Deserialize(fs);

            if (dlk.b || dlk.y == null || dlk.a == null)
                throw new Exception(MSG_INVALID_PUBLIC_KEY);

            DHValidationParameters vp = null;

            if (dlk.s != null)
                vp = new DHValidationParameters(dlk.s, dlk.c);

            DHParameters dhp = new DHParameters
            (
                  new BigInteger(dlk.p)
                , new BigInteger(dlk.g)
                , new BigInteger(dlk.q)
                , dlk.m
                , dlk.l
                , new BigInteger (dlk.j)
                , vp
            );

            pbk = new DHPublicKeyParameters
            (
                  new BigInteger(dlk.y)
                , dhp
                , new DerObjectIdentifier(dlk.a)
            );

            Program.ClearDliesKey(dlk);

            if (!File.Exists(_private_key))
                throw new Exception(MSG_INVALID_PRIVATE_KEY);

            using (FileStream fs = File.OpenRead(_private_key))
                dlk = (DliesKey)xml.Deserialize(fs);

            if (!dlk.b || dlk.x == null || dlk.a == null)
                throw new Exception(MSG_INVALID_PRIVATE_KEY);

            vp = null;

            if (dlk.s != null)
                vp = new DHValidationParameters(dlk.s, dlk.c);

            dhp = new DHParameters
            (
                  new BigInteger(dlk.p)
                , new BigInteger(dlk.g)
                , new BigInteger(dlk.q)
                , dlk.m
                , dlk.l
                , new BigInteger(dlk.j)
                , vp
            );

            pvk = new DHPrivateKeyParameters
            (
                  new BigInteger(dlk.x)
                , dhp
                , new DerObjectIdentifier(dlk.a)
            );

            Program.ClearDliesKey(dlk);
        }

        //----------------------------------------------------------------------------------

        private static void IesCrypt 
        (
              bool    encryption
            , string  mode
            , IDigest digest
            , Stream  src
            , Stream  dest
        ){
            IBasicAgreement   iba = null;
            IBlockCipher      ibc = null;
            ICipherParameters pbk = null;
            ICipherParameters pvk = null;
            IesEngine         ie  = null;
            int               bsz = _buffersize;

            switch (mode)
            {
                case ECIES:
                    Program.EciesImportKeys(ref pbk, ref pvk);
                    iba = new ECDHCBasicAgreement();
                    break;

                case DLIES:
                    Program.DliesImportKeys(ref pbk, ref pvk);
                    iba = new DHBasicAgreement();
                    break;
            }

            switch (_ies_cipher)
            {
                case THREEFISH:
                    ibc = new ThreefishEngine(_keysize);
                    break;

                case RIJNDAEL:
                    ibc = new RijndaelEngine(_blocksize);
                    break;

                case AES:
                    ibc = new AesEngine();
                    break;

                case DES:
                    ibc = new DesEngine();
                    break;

                case TDES:
                    ibc = new DesEdeEngine();
                    break;

                case RC2:
                    ibc = new RC2Engine();
                    break;

                case RC5:
                    ibc = _rc5b64 ? (IBlockCipher)new RC564Engine() : new RC532Engine();
                    break;

                case RC6:
                    ibc = new RC6Engine();
                    break;

                case CAMELLIA:
                    ibc = new CamelliaEngine();
                    break;

                case SKIPJACK:
                    ibc = new SkipjackEngine();
                    break;

                case GOST:
                    ibc = new Gost28147Engine();
                    break;

                case TWOFISH:
                    ibc = new TwofishEngine();
                    break;

                case TNEPRES:
                    ibc = new TnepresEngine();
                    break;

                case BLOWFISH:
                    ibc = new BlowfishEngine();
                    break;

                case SERPENT:
                    ibc = new SerpentEngine();
                    break;

                case CAST5:
                    ibc = new Cast5Engine();
                    break;

                case CAST6:
                    ibc = new Cast6Engine();
                    break;

                case IDEA:
                    ibc = new IdeaEngine();
                    break;

                case NOEKEON:
                    ibc = new NoekeonEngine();
                    break;

                case SEED:
                    ibc = new SeedEngine();
                    break;

                case TEA:
                    ibc = new TeaEngine();
                    break;

                case XTEA:
                    ibc = new XteaEngine();
                    break;

                default:
                    if (!string.IsNullOrEmpty(_ies_cipher))
                        throw new Exception(MSG_INVALID_IES_CIPHER);

                    break;
            }

            if (ibc != null) ie = new IesEngine
            (
                  iba
                , new Kdf2BytesGenerator(digest)
                , new HMac(digest)
                , new PaddedBufferedBlockCipher
                  (
                        Program.GetBlockCipherMode(ibc)
                      , Program.GetBouncyCastlePadding()
                  )
            );

            else ie = new IesEngine
            (
                  iba
                , new Kdf2BytesGenerator(digest)
                , new HMac(digest)
            );

            BufferedIesCipher bic = new BufferedIesCipher(ie);

            bic.Init
            (
                  encryption
                , pvk
                , pbk
                , ibc == null ? new IesParameters(_sk.key, _sk.iv, _keysize) :
                  new IesWithCipherParameters(_sk.key, _sk.iv, digest.GetDigestSize() * 8, _keysize)
            );

            if (!encryption)
            {
                bsz += digest.GetDigestSize();

                if (ibc != null)
                    bsz += ibc.GetBlockSize();
            }

            Program.Write(bic, bsz, src, dest);
        }

        //----------------------------------------------------------------------------------

        private static IDigest GetBouncyCastleDigest ()
        {
            switch (_hash)
            {
                case HASH_KECCAK224:
                    return new KeccakDigest(224);

                case HASH_KECCAK256:
                    return new KeccakDigest(256);

                case HASH_KECCAK384:
                    return new KeccakDigest(384);

                case HASH_KECCAK512:
                    return new KeccakDigest(512);

                case HASH_RIPEMD128:
                    return new RipeMD128Digest();

                case HASH_RIPEMD160:
                    return new RipeMD160Digest();

                case HASH_RIPEMD256:
                    return new RipeMD256Digest();

                case HASH_RIPEMD320:
                    return new RipeMD320Digest();

                case HASH_SHA1:
                    return new Sha1Digest();

                case HASH_SHA224:
                    return new Sha224Digest();

                case HASH_SHA256:
                    return new Sha256Digest();

                case HASH_SHA384:
                    return new Sha384Digest();

                case HASH_SHA512:
                    return new Sha512Digest();

                case HASH_MD2:
                    return new MD2Digest();

                case HASH_MD4:
                    return new MD4Digest();

                case HASH_MD5:
                    return new MD5Digest();

                case HASH_SKEIN256:
                    return new SkeinDigest(256, 32);

                case HASH_SKEIN512:
                    return new SkeinDigest(512, 64);

                case HASH_WHIRLPOOL:
                    return new WhirlpoolDigest();

                default:
                    throw new Exception(MSG_INVALID_HASH);
            }
        }

        //----------------------------------------------------------------------------------

        private static string ComputeHashFromStream (HashAlgorithm h, Stream s)
        {
            h.Initialize();

            byte[]        b  = h.ComputeHash(s);
            StringBuilder sb = new StringBuilder();

            for (int i = 0, l = b.Length; i < l; ++i)
            {
                sb.Append(b[i].ToString("x2"));
                b[i] = 0;
            }

            return sb.ToString();
        }

        //----------------------------------------------------------------------------------

        private static string Digest (Stream s)
        {
            HashAlgorithm h;

            switch (_hash)
            {
                case HASH_BLAKE224:
                    h = new HashAlgorithmWrapper(new Blake224());
                    break;

                case HASH_BLAKE256:
                    h = new HashAlgorithmWrapper(new Blake256());
                    break;

                case HASH_BLAKE384:
                    h = new HashAlgorithmWrapper(new Blake384());
                    break;

                case HASH_BLAKE512:
                    h = new HashAlgorithmWrapper(new Blake512());
                    break;

                case HASH_BMW224:
                    h = new HashAlgorithmWrapper(new BlueMidnightWish224());
                    break;

                case HASH_BMW256:
                    h = new HashAlgorithmWrapper(new BlueMidnightWish256());
                    break;

                case HASH_BMW384:
                    h = new HashAlgorithmWrapper(new BlueMidnightWish384());
                    break;

                case HASH_BMW512:
                    h = new HashAlgorithmWrapper(new BlueMidnightWish512());
                    break;

                case HASH_CUBE224:
                    h = new HashAlgorithmWrapper(new CubeHash224());
                    break;

                case HASH_CUBE256:
                    h = new HashAlgorithmWrapper(new CubeHash256());
                    break;

                case HASH_CUBE384:
                    h = new HashAlgorithmWrapper(new CubeHash384());
                    break;

                case HASH_CUBE512:
                    h = new HashAlgorithmWrapper(new CubeHash512());
                    break;

                case HASH_ECHO224:
                    h = new HashAlgorithmWrapper(new Echo224());
                    break;

                case HASH_ECHO256:
                    h = new HashAlgorithmWrapper(new Echo256());
                    break;

                case HASH_ECHO384:
                    h = new HashAlgorithmWrapper(new Echo384());
                    break;

                case HASH_ECHO512:
                    h = new HashAlgorithmWrapper(new Echo512());
                    break;

                case HASH_FUGUE224:
                    h = new HashAlgorithmWrapper(new Fugue224());
                    break;

                case HASH_FUGUE256:
                    h = new HashAlgorithmWrapper(new Fugue256());
                    break;

                case HASH_FUGUE384:
                    h = new HashAlgorithmWrapper(new Fugue384());
                    break;

                case HASH_FUGUE512:
                    h = new HashAlgorithmWrapper(new Fugue512());
                    break;

                case HASH_GROESTL224:
                    h = new HashAlgorithmWrapper(new Groestl224());
                    break;

                case HASH_GROESTL256:
                    h = new HashAlgorithmWrapper(new Groestl256());
                    break;

                case HASH_GROESTL384:
                    h = new HashAlgorithmWrapper(new Groestl384());
                    break;

                case HASH_GROESTL512:
                    h = new HashAlgorithmWrapper(new Groestl512());
                    break;

                case HASH_HAMSI224:
                    h = new HashAlgorithmWrapper(new Hamsi224());
                    break;

                case HASH_HAMSI256:
                    h = new HashAlgorithmWrapper(new Hamsi256());
                    break;

                case HASH_HAMSI384:
                    h = new HashAlgorithmWrapper(new Hamsi384());
                    break;

                case HASH_HAMSI512:
                    h = new HashAlgorithmWrapper(new Hamsi512());
                    break;

                case HASH_JH224:
                    h = new HashAlgorithmWrapper(new JH224());
                    break;

                case HASH_JH256:
                    h = new HashAlgorithmWrapper(new JH256());
                    break;

                case HASH_JH384:
                    h = new HashAlgorithmWrapper(new JH384());
                    break;

                case HASH_JH512:
                    h = new HashAlgorithmWrapper(new JH512());
                    break;

                case HASH_KECCAK224:
                    h = new HashAlgorithmWrapper(new Keccak224());
                    break;

                case HASH_KECCAK256:
                    h = new HashAlgorithmWrapper(new Keccak256());
                    break;

                case HASH_KECCAK384:
                    h = new HashAlgorithmWrapper(new Keccak384());
                    break;

                case HASH_KECCAK512:
                    h = new HashAlgorithmWrapper(new Keccak512());
                    break;

                case HASH_LUFFA224:
                    h = new HashAlgorithmWrapper(new Luffa224());
                    break;

                case HASH_LUFFA256:
                    h = new HashAlgorithmWrapper(new Luffa256());
                    break;

                case HASH_LUFFA384:
                    h = new HashAlgorithmWrapper(new Luffa384());
                    break;

                case HASH_LUFFA512:
                    h = new HashAlgorithmWrapper(new Luffa512());
                    break;

                case HASH_SHABAL224:
                    h = new HashAlgorithmWrapper(new Shabal224());
                    break;

                case HASH_SHABAL256:
                    h = new HashAlgorithmWrapper(new Shabal256());
                    break;

                case HASH_SHABAL384:
                    h = new HashAlgorithmWrapper(new Shabal384());
                    break;

                case HASH_SHABAL512:
                    h = new HashAlgorithmWrapper(new Shabal512());
                    break;

                case HASH_SHAVITE_224:
                    h = new HashAlgorithmWrapper(new SHAvite3_224());
                    break;

                case HASH_SHAVITE_256:
                    h = new HashAlgorithmWrapper(new SHAvite3_256());
                    break;

                case HASH_SHAVITE_384:
                    h = new HashAlgorithmWrapper(new SHAvite3_384());
                    break;

                case HASH_SHAVITE_512:
                    h = new HashAlgorithmWrapper(new SHAvite3_512());
                    break;

                case HASH_SIMD224:
                    h = new HashAlgorithmWrapper(new SIMD224());
                    break;

                case HASH_SIMD256:
                    h = new HashAlgorithmWrapper(new SIMD256());
                    break;

                case HASH_SIMD384:
                    h = new HashAlgorithmWrapper(new SIMD384());
                    break;

                case HASH_SIMD512:
                    h = new HashAlgorithmWrapper(new SIMD512());
                    break;

                case HASH_SKEIN224:
                    h = new HashAlgorithmWrapper(new Skein224());
                    break;

                case HASH_SKEIN256:
                    h = new HashAlgorithmWrapper(new Skein256());
                    break;

                case HASH_SKEIN384:
                    h = new HashAlgorithmWrapper(new Skein384());
                    break;

                case HASH_SKEIN512:
                    h = new HashAlgorithmWrapper(new Skein512());
                    break;

                case HASH_RIPEMD:
                    h = new HashAlgorithmWrapper(new RIPEMD());
                    break;

                case HASH_RIPEMD128:
                    h = new HashAlgorithmWrapper(new RIPEMD128());
                    break;

                case HASH_RIPEMD160:
                    h = RIPEMD160.Create();
                    break;

                case HASH_RIPEMD256:
                    h = new HashAlgorithmWrapper(new RIPEMD256());
                    break;

                case HASH_RIPEMD320:
                    h = new HashAlgorithmWrapper(new RIPEMD320());
                    break;

                case HASH_SHA512:
                    h = SHA512.Create();
                    break;

                case HASH_SHA384:
                    h = SHA384.Create();
                    break;

                case HASH_SHA256:
                    h = SHA256.Create();
                    break;

                case HASH_SHA224:
                    h = new HashAlgorithmWrapper(new SHA224());
                    break;

                case HASH_SHA1:
                    h = SHA1.Create();
                    break;

                case HASH_SHA0:
                    h = new HashAlgorithmWrapper(new SHA0());
                    break;

                case HASH_MD5:
                    h = MD5.Create();
                    break;

                case HASH_MD4:
                    h = new HashAlgorithmWrapper(new MD4());
                    break;

                case HASH_MD2:
                    h = new HashAlgorithmWrapper(new MD2());
                    break;

                case GOST:
                    h = new HashAlgorithmWrapper(new Gost());
                    break;

                case HASH_GRINDAHL256:
                    h = new HashAlgorithmWrapper(new Grindahl256());
                    break;

                case HASH_GRINDAHL512:
                    h = new HashAlgorithmWrapper(new Grindahl512());
                    break;

                case HASH_HAS160:
                    h = new HashAlgorithmWrapper(new HAS160());
                    break;

                case HASH_HAVAL3_128:
                    h = new HashAlgorithmWrapper(new Haval_3_128());
                    break;

                case HASH_HAVAL3_160:
                    h = new HashAlgorithmWrapper(new Haval_3_160());
                    break;

                case HASH_HAVAL3_192:
                    h = new HashAlgorithmWrapper(new Haval_3_192());
                    break;

                case HASH_HAVAL3_224:
                    h = new HashAlgorithmWrapper(new Haval_3_224());
                    break;

                case HASH_HAVAL3_256:
                    h = new HashAlgorithmWrapper(new Haval_3_256());
                    break;

                case HASH_HAVAL4_128:
                    h = new HashAlgorithmWrapper(new Haval_4_128());
                    break;

                case HASH_HAVAL4_160:
                    h = new HashAlgorithmWrapper(new Haval_4_160());
                    break;

                case HASH_HAVAL4_192:
                    h = new HashAlgorithmWrapper(new Haval_4_192());
                    break;

                case HASH_HAVAL4_224:
                    h = new HashAlgorithmWrapper(new Haval_4_224());
                    break;

                case HASH_HAVAL4_256:
                    h = new HashAlgorithmWrapper(new Haval_4_256());
                    break;

                case HASH_HAVAL5_128:
                    h = new HashAlgorithmWrapper(new Haval_5_128());
                    break;

                case HASH_HAVAL5_160:
                    h = new HashAlgorithmWrapper(new Haval_5_160());
                    break;

                case HASH_HAVAL5_192:
                    h = new HashAlgorithmWrapper(new Haval_5_192());
                    break;

                case HASH_HAVAL5_224:
                    h = new HashAlgorithmWrapper(new Haval_5_224());
                    break;

                case HASH_HAVAL5_256:
                    h = new HashAlgorithmWrapper(new Haval_5_256());
                    break;

                case HASH_PANAMA:
                    h = new HashAlgorithmWrapper(new Panama());
                    break;

                case HASH_RG32:
                    h = new HashAlgorithmWrapper(new RadioGatun32());
                    break;

                case HASH_RG64:
                    h = new HashAlgorithmWrapper(new RadioGatun64());
                    break;

                case HASH_SNEFRU4_128:
                    h = new HashAlgorithmWrapper(new Snefru_4_128());
                    break;

                case HASH_SNEFRU4_256:
                    h = new HashAlgorithmWrapper(new Snefru_4_256());
                    break;

                case HASH_SNEFRU8_128:
                    h = new HashAlgorithmWrapper(new Snefru_8_128());
                    break;

                case HASH_SNEFRU8_256:
                    h = new HashAlgorithmWrapper(new Snefru_8_256());
                    break;

                case HASH_TIGER2:
                    h = new HashAlgorithmWrapper(new Tiger2());
                    break;

                case HASH_TIGER3_192:
                    h = new HashAlgorithmWrapper(new Tiger_3_192());
                    break;

                case HASH_TIGER4_192:
                    h = new HashAlgorithmWrapper(new Tiger_4_192());
                    break;

                case HASH_WHIRLPOOL:
                    h = new HashAlgorithmWrapper(new Whirlpool());
                    break;

                case HASH_AP:
                    h = new HashAlgorithmWrapper(new AP());
                    break;

                case HASH_BERNSTEIN:
                    h = new HashAlgorithmWrapper(new Bernstein());
                    break;

                case HASH_BERNSTEIN1:
                    h = new HashAlgorithmWrapper(new Bernstein1());
                    break;

                case HASH_BKDR:
                    h = new HashAlgorithmWrapper(new BKDR());
                    break;

                case HASH_DEK:
                    h = new HashAlgorithmWrapper(new DEK());
                    break;

                case HASH_DJB:
                    h = new HashAlgorithmWrapper(new DJB());
                    break;

                case HASH_DOTNET:
                    h = new HashAlgorithmWrapper(new DotNet());
                    break;

                case HASH_ELF:
                    h = new HashAlgorithmWrapper(new ELF());
                    break;

                case HASH_FNV:
                    h = new HashAlgorithmWrapper(new FNV());
                    break;

                case HASH_FNV1A:
                    h = new HashAlgorithmWrapper(new FNV1a());
                    break;

                case HASH_FNV64:
                    h = new HashAlgorithmWrapper(new FNV64());
                    break;

                case HASH_FNV1A64:
                    h = new HashAlgorithmWrapper(new FNV1a64());
                    break;

                case HASH_JENKINS3:
                    h = new HashAlgorithmWrapper(new Jenkins3());
                    break;

                case HASH_JS:
                    h = new HashAlgorithmWrapper(new JS());
                    break;

                case HASH_MURMUR2:
                    h = new HashAlgorithmWrapper(new Murmur2());
                    break;

                case HASH_MURMUR2_64:
                    h = new HashAlgorithmWrapper(new Murmur2_64());
                    break;

                case HASH_MURMUR3:
                    h = new HashAlgorithmWrapper(new Murmur3());
                    break;

                case HASH_MURMUR3_128:
                    h = new HashAlgorithmWrapper(new Murmur3_128());
                    break;

                case HASH_ONEATTIME:
                    h = new HashAlgorithmWrapper(new OneAtTime());
                    break;

                case HASH_PJW:
                    h = new HashAlgorithmWrapper(new PJW());
                    break;

                case HASH_ROTATING:
                    h = new HashAlgorithmWrapper(new Rotating());
                    break;

                case HASH_RS:
                    h = new HashAlgorithmWrapper(new RS());
                    break;

                case HASH_SDBM:
                    h = new HashAlgorithmWrapper(new SDBM());
                    break;

                case HASH_SHIFTANDXOR:
                    h = new HashAlgorithmWrapper(new ShiftAndXor());
                    break;

                case HASH_SUPERFAST:
                    h = new HashAlgorithmWrapper(new SuperFast());
                    break;

                case HASH_SIPHASH:
                    h = new HashAlgorithmWrapper(new HashLib.Hash64.SipHash());
                    break;

                default:
                    throw new Exception(MSG_INVALID_HASH);
            }

            return Program.ComputeHashFromStream(h, s);
        }

        //----------------------------------------------------------------------------------

        private static string Checksum (Stream s)
        {
            HashAlgorithm h;

            switch (_hash)
            {
                case HASH_ADLER32:
                    h = new HashAlgorithmWrapper(new Adler32());
                    break;

                case HASH_CRC32_IEEE:
                    h = new HashAlgorithmWrapper(new CRC32_IEEE());
                    break;

                case HASH_CRC32_CASTAGNOLI:
                    h = new HashAlgorithmWrapper(new CRC32_CASTAGNOLI());
                    break;

                case HASH_CRC32_KOOPMAN:
                    h = new HashAlgorithmWrapper(new CRC32_KOOPMAN());
                    break;

                case HASH_CRC32_Q:
                    h = new HashAlgorithmWrapper(new CRC32_Q());
                    break;

                case HASH_CRC64_ISO:
                    h = new HashAlgorithmWrapper(new CRC64_ISO());
                    break;

                case HASH_CRC64_ECMA:
                    h = new HashAlgorithmWrapper(new CRC64_ECMA());
                    break;

                default:
                    throw new Exception(MSG_INVALID_HASH);
            }

            return Program.ComputeHashFromStream(h, s);
        }

        //----------------------------------------------------------------------------------

        private static string GetRandomString (int length, bool unesc = false)
        {
            if (length < 1)
                throw new ArgumentOutOfRangeException("length");

            char                     cc;
            bool                     bc = false;
            RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider();
            Random                   rd = new Random();
            StringBuilder            sb = new StringBuilder();
            byte[]                   br = new byte[length];
            string                   cp = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv" +
                                          "wxyz0123456789!#%&()*+-,./:;<>?@[\\]^_{|}~";
            rg.GetBytes(br);
            length = cp.Length - 1;

            foreach (byte b in br)
            {
                cc = cp[b % length];

                if (unesc)
                {
                    while (bc)
                    {
                        if (cc != 'x' && cc != 'u')
                        {
                            bc = false;
                            break;
                        }

                        cc = cp[rd.Next(0, length)];
                    }

                    if (!bc && cc == '\\')
                        bc = true;
                }

                sb.Append(cc);
            }

            return sb.ToString();
        }

        //----------------------------------------------------------------------------------

        private static void RandomGen
        (
              short  blocksize
            , string target
            , bool   hightblock = false
        ){
            string snf = "\r\"";

			if (string.IsNullOrEmpty(_password))
			{
            	Messenger.Print
            	(
            		  Messenger.Icon.INFORMATION
                    , "Random Password for " + target + " -> \""
            	);
            	
            	Messenger.Print
            	(
                      (_password = Program.GetRandomString(24, !_unesc)) + snf
               		, new ConsoleColor[] { ConsoleColor.DarkYellow, ConsoleColor.Gray }
				);
			}

            if (!_saltleaking && string.IsNullOrEmpty(_salt))
			{
	            Messenger.Print
	            (
	            	  Messenger.Icon.INFORMATION
                    , "Random Salt for " + target + " -> \""
	           	);
	           	
	            Messenger.Print
	            (
	                  (_salt = Program.GetRandomString(8)) + snf
	                , new ConsoleColor[] { ConsoleColor.DarkYellow, ConsoleColor.Gray }
	            );
	        }

            blocksize /= (short)(hightblock || blocksize > 64 ? 8 : 4);
            if (blocksize > 1 && string.IsNullOrEmpty(_iv))
            {
                Messenger.Print
                (
                      Messenger.Icon.INFORMATION
                    , "Random IV for " + target + " -> \""
                );

                Messenger.Print
                (
                      (_iv = Program.GetRandomString(blocksize, !_unesc)) + snf
                    , new ConsoleColor[] { ConsoleColor.DarkYellow, ConsoleColor.Gray }
                );
            }
        }

        //----------------------------------------------------------------------------------

        private static void DefinePassword (bool asymmetric = false)
        {
            bool   b = false;
            string s = "The password does not match!";
            _haspwd  = false;

            if (string.IsNullOrEmpty(_password)) do
            {
                if (b && !Program.Question(s + "\n\n> Do you want to repeat the password entry?", false))
                {
                    if (!_raise)
                        _password = string.Empty;

                    throw new Exception(s);
                }

                _password = Program.Prompt
                (
                      asymmetric ? MSG_PRIVATE_KEY_PWD : MSG_PASSWORD
                    , true
                );
            }
            while (b = _password != Program.Prompt(MSG_CONFIRM_PWD, true));

            if (!asymmetric && !_saltleaking && string.IsNullOrEmpty(_salt))
            {
                _salt        = Program.Prompt(MSG_SALT, false, 8, true);
                _saltleaking = true;
            }

            _haspwd = true;
        }

        //----------------------------------------------------------------------------------

        private static void ProvideKey (string target, int nfiles, bool hightblock = false)
        {
            if (!string.IsNullOrEmpty(_key))
                Program.SetSymmetricKey(_keysize, _blocksize, hightblock);

            else
            {
                if (!_random || _cop == CryptOperation.DECRYPT)
                    Program.DefinePassword();

                else
                {
                    Program.RandomGen
                    (
                          _blocksize
                        , !_tellapart && nfiles > 1 ? nfiles + FILES : '"' +
                          Path.GetFileName(target) + '"'
                        , hightblock
                    );

                    if (!_tellapart)
                        _random = false;
                }

                Program.KeyGen(_keysize, _blocksize, hightblock);

                if (_tellapart)
                {
                    _key         = string.Empty;
                    _iv          = string.Empty;
                    _password    = string.Empty;
                    _salt        = string.Empty;
                    _saltleaking = false;
                }
            }
        }

        //----------------------------------------------------------------------------------

        private static void ValidateParams (ulong ul1, ulong ul2)
        {
            bool b;
            
            if ((ul1 & 0x1) == 0x1 && !_rfc4648)
            {
                _rfc4648 = true;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "no-rfc4648")
                    , false
                    , true
                );
            }
            
            if ((ul1 & 0x10) == 0x10 && _b32hex)
            {
                _b32hex = false;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "b32-hex")
                    , false
                    , true
                );
            }
            
            if ((ul1 & 0x100) == 0x100 && _code != CODE)
            {
                _code = CODE;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "base-code")
                    , false
                    , true
                );
            }
            
            if (((ul1 & 0x1000) == 0x1000 || _cop != CryptOperation.ENCRYPT) && _charsperline != 0)
            {
                _charsperline = 0;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "base-line-wrap")
                    , false
                    , true
                );
            }

            if ((ul1 & 0x10000) == 0x10000 && _rounds != 20)
            {
                _rounds = 20;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "rounds")
                    , false
                    , true
                );
            }

            if ((ul1 & 0x100000) == 0x100000 && _rc5b64)
            {
                _rc5b64 = false;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "rc5-64b")
                    , false
                    , true
                );
            }

            if ((ul1 & 0x1000000) == 0x1000000 && _ksa3)
            {
                _ksa3 = false;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "vmpc-ksa3")
                    , false
                    , true
                );
            }

            if ((ul1 & 0x10000000) == 0x10000000 && _buffersize != 1024)
            {
                _buffersize = 1024;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "max-buffer-size")
                    , false
                    , true
                );
            }

            if ((ul1 & 0x100000000) == 0x100000000 && !string.IsNullOrEmpty(_key))
            {
                _key = string.Empty;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "key")
                    , false
                    , true
                );
            }

            if ((ul1 & 0x1000000000) == 0x1000000000 && !string.IsNullOrEmpty(_iv))
            {
                _iv = string.Empty;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "initial-vector")
                    , false
                    , true
                );
            }

            if ((ul1 & 0x10000000000) == 0x10000000000 && !string.IsNullOrEmpty(_password))
            {
                _password = string.Empty;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "password")
                    , false
                    , true
                );
            }

            if ((ul1 & 0x100000000000) == 0x100000000000 && !string.IsNullOrEmpty(_salt))
            {
                _salt = string.Empty;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "salt")
                    , false
                    , true
                );
            }

            if ((ul1 & 0x1000000000000) == 0x1000000000000 && _hash != HASH_SHA512)
            {
                _hash = HASH_SHA512;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "hash")
                    , false
                    , true
                );
            }

            if ((ul1 & 0x10000000000000) == 0x10000000000000 && _iterations != 1000)
            {
                _iterations = 1000;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "iterations")
                    , false
                    , true
                );
            }

            if ((ul1 & 0x100000000000000) == 0x100000000000000 && _ciphermode != CipherMode.CBC)
            {
                _ciphermode = CipherMode.CBC;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "cipher-mode")
                    , false
                    , true
                );
            }

            if ((ul1 & 0x1000000000000000) == 0x1000000000000000 && _padding != CryptPadding.PKCS7)
            {
                _padding = CryptPadding.PKCS7;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "padding")
                    , false
                    , true
                );
            }

            if ((ul2 & 0x1) == 0x1 && _random)
            {
                _random = false;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "random-gen")
                    , false
                    , true
                );
            }

            if ((ul2 & 0x10) == 0x10 && _blocksize != -1)
            {
                _blocksize = -1;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "block-size")
                    , false
                    , true
                );
            }

            if ((ul2 & 0x100) == 0x100 && _feedbacksize != -1)
            {
                _feedbacksize = -1;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "feedback-size")
                    , false
                    , true
                );
            }

            if ((ul2 & 0x1000) == 0x1000 && _keysize != -1)
            {
                _keysize = -1;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "key-size")
                    , false
                    , true
                );
            }

            if ((ul2 & 0x10000) == 0x10000)
            {
                if (!string.IsNullOrEmpty(_public_key))
                {
                    _public_key = string.Empty;
                    Messenger.Print
                    (
                          Messenger.Icon.WARNING
                        , string.Format(MSG_GENERIC_USE, "public-key")
                        , false
                        , true
                    );
                }

                if (!string.IsNullOrEmpty(_private_key))
                {
                    _private_key = string.Empty;
                    Messenger.Print
                    (
                          Messenger.Icon.WARNING
                        , string.Format(MSG_GENERIC_USE, "private-key")
                        , false
                        , true
                    );
                }
            }

            if ((ul2 & 0x100000) == 0x100000)
            {
                if (!string.IsNullOrEmpty(_cerfile))
                {
                    _cerfile = string.Empty;
                    Messenger.Print
                    (
                          Messenger.Icon.WARNING
                        , string.Format(MSG_GENERIC_USE, "x509-file")
                        , false
                        , true
                    );
                }

                if (!string.IsNullOrEmpty(_cerstore))
                {
                    _cerstore = string.Empty;
                    Messenger.Print
                    (
                          Messenger.Icon.WARNING
                        , string.Format(MSG_GENERIC_USE, "x509-name")
                        , false
                        , true
                    );
                }
            }

            if ((ul2 & 0x1000000) == 0x1000000 && _format != CryptFormat.UNKNOWN)
            {
                _format = CryptFormat.UNKNOWN;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "format")
                    , false
                    , true
                );
            }

            if ((ul2 & 0x10000000) == 0x10000000 && _padding == CryptPadding.OAEP)
            {
                _padding = CryptPadding.PKCS7;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "oaep")
                    , false
                    , true
                );
            }

            if ((ul2 & 0x100000000) == 0x100000000 && _ska != SymmetricKeyAlgorithmTag.Aes256)
            {
                _ska = SymmetricKeyAlgorithmTag.Aes256;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "pgp-cipher")
                    , false
                    , true
                );
            }

            if ((b = (ul2 & 0x1000000000) == 0x1000000000) || (!_generator && !_export))
            {
                if (!string.IsNullOrEmpty(_pgp_id))
                {
                    _pgp_id = string.Empty;
                    Messenger.Print
                    (
                          Messenger.Icon.WARNING
                        , string.Format(MSG_GENERIC_USE, "pgp-id")
                        , false
                        , true
                    );
                }

                if (_sha1)
                {
                    _sha1 = false;
                    Messenger.Print
                    (
                          Messenger.Icon.WARNING
                        , string.Format(MSG_GENERIC_USE, "pgp-sha1")
                        , false
                        , true
                    );
                }

                if (!string.IsNullOrEmpty(_pgp_master))
                {
                    _pgp_master = string.Empty;
                    Messenger.Print
                    (
                          Messenger.Icon.WARNING
                        , string.Format(MSG_GENERIC_USE, "pgp-master")
                        , false
                        , true
                    );
                }

                if (_pgp_sign && b)
                {
                    _pgp_sign = false;
                    Messenger.Print
                    (
                          Messenger.Icon.WARNING
                        , string.Format(MSG_GENERIC_USE, "pgp-sign")
                        , false
                        , true
                    );
                }
            }

            if ((ul2 & 0x10000000000) == 0x10000000000 && _crossbreeding)
            {
                _crossbreeding = false;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "crossbreeding")
                    , false
                    , true
                );
            }

            if ((ul2 & 0x100000000000) == 0x100000000000 && !string.IsNullOrEmpty(_sbox))
            {
                _sbox = string.Empty;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "gost-box")
                    , false
                    , true
                );
            }

            if ((ul2 & 0x1000000000000) == 0x1000000000000 && _ies_cipher != AES)
            {
                _ies_cipher = AES;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "ies-cipher")
                    , false
                    , true
                );
            }

            if ((ul2 & 0x10000000000000) == 0x10000000000000)
            {
                if (_curve != DEFCURVE)
                {
                    _curve = DEFCURVE;
                    Messenger.Print
                    (
                          Messenger.Icon.WARNING
                        , string.Format(MSG_GENERIC_USE, "curve")
                        , false
                        , true
                    );
                }

                if (_curvestore != SEC)
                {
                    _curvestore = SEC;
                    Messenger.Print
                    (
                          Messenger.Icon.WARNING
                        , string.Format(MSG_GENERIC_USE, "curve-store")
                        , false
                        , true
                    );
                }
            }

            if ((ul2 & 0x100000000000000) == 0x100000000000000 && _without_iv)
            {
                _without_iv = false;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, "without-iv-tweak")
                    , false
                    , true
                );
            }

            if ((ul2 & 0x1000000000000000) == 0x1000000000000000 && _rsa_bc)
            {
                _rsa_bc = false;
                Messenger.Print
                (
                      Messenger.Icon.WARNING
                    , string.Format(MSG_GENERIC_USE, RSA_BC)
                    , false
                    , true
                );
            }
        }

        //----------------------------------------------------------------------------------

        private static void AssertPgpAlgorithm (PublicKeyAlgorithmTag pkat)
        {
            string s = " algorithm has been detected and asserted!";

            switch (pkat)
            {
                case PublicKeyAlgorithmTag.RsaGeneral:
                    if (_pgp_algorithm != RSA) 
                    {
                        _pgp_algorithm = RSA;
                        Messenger.Print(Messenger.Icon.WARNING, RSA + s);
                    }
                    break;

                case PublicKeyAlgorithmTag.ElGamalGeneral:
                    if (_pgp_algorithm != ELGAMAL)
                    {
                        _pgp_algorithm = ELGAMAL;
                        Messenger.Print(Messenger.Icon.WARNING, ELGAMAL + s);
                    }
                    break;

                default:
                    throw new Exception(MSG_INVALID_PGP_ALGORITHM);
            }
        }

        //----------------------------------------------------------------------------------

        private static bool ValidatePath (string path)
        {
            if (string.IsNullOrEmpty(path))
                return false;

            char[] chrs = Path.GetInvalidPathChars();
            
            foreach (char c in chrs)
                if (path.IndexOf(c) != -1)
                    return false;

            if (!Directory.Exists(Path.GetDirectoryName(Path.GetFullPath(path))))
                return false;

            return true;
        }

        //----------------------------------------------------------------------------------

        private static bool Question 
        (
              string         msg
            , bool           exit = false
            , Messenger.Icon icon = Messenger.Icon.QUESTION
        ){
            bool b = ConsoleKey.Y == Messenger.Print
            (
                  icon
                , msg
                , new ConsoleKey[] { ConsoleKey.Y, ConsoleKey.N }
                , true
                , true
            );

            if (!b && exit)
            {
                Messenger.Print(Messenger.Icon.WARNING, MSG_PROCESS_CANCELLED);
                Environment.Exit(0);
            }

            return b;
        }

        //----------------------------------------------------------------------------------

        private static bool OverwriteFileCheck (string file, bool overwrite = false)
        {
            if (File.Exists(file) && !overwrite)
            {
                overwrite = Program.Question
                (
                    String.Format
                    (
                          "The file \"{0}\" already exists!\n\n> Do you want to overwrite?"
                        , Path.GetFullPath(file)
                    )
                    , true
                );
            }

            return true;
        }

        //----------------------------------------------------------------------------------

        private static void ExceptionControl (int id)
        {
            if (_e_num != id)
            {
                _e_num = id;
                _e_cnt = 1;
            }

            else if (++_e_cnt > _e_max)
            {
                Program.Question
                (
                      string.Format(MSG_EXCEPTION_LOOPING, _e_max) +
                      MSG_CONTINUE_QUESTION
                    , true
                );

                _e_num = 0;
            }
        }

        //----------------------------------------------------------------------------------

        private static void MoveFile (string src, string dest)
        {
            if (File.Exists(src))
            {
                bool b = File.Exists(dest);

                Messenger.Print
                (
                      Messenger.Icon.INFORMATION
                    , string.Format
                      (
                            "{0} the file \"{1}\" {2} \"{3}\""
                          , b ? "Overwriting" : "Moving"
                          , Path.GetFileName(dest)
                          , b ? "in" : "to"
                          , Path.GetDirectoryName(dest)
                      )
                    , false
                    , true
                );

                using (FileStream fsr = File.OpenRead(src))
                    using (FileStream fsw = File.Create(dest))
                        Program.Write(fsr, fsw, fsr.Length);

                File.Delete(src);
            }
        }

        //----------------------------------------------------------------------------------

        private static void ShowBanner ()
        {
            if (_banner)
            {
                Version v = Assembly.GetExecutingAssembly().GetName().Version;
                Messenger.Print
                (
                      Messenger.Frame.SIMPLE
                    , "Crypter Tool v." + v.Major + "." + v.Minor + "." + v.Build + "." + 
                       v.Revision + "\n(c) 2013 by José A. Rojo L."
                    , ConsoleColor.DarkGreen
                    , ConsoleColor.DarkGreen
                    , true
                );

                _banner = false;
            }
        }

        //----------------------------------------------------------------------------------

        private static void ShowHelp ()
        {
            Program.ShowBanner();
            Messenger.Print
            (
                  "\n Usage:\n\n\t\rcrypter [options...] input-file-name\n"                           +
                  "\n \rOptions:\n\n"                                                                 +
                  "\t\r-m  --mode            \rAlgorithm mode. Use the help combined with this"       +
                  "\n\t\t\t      modifier to list or for more info.\n\n"                              +
                  "\t\r-e  --encrypt-encode  \rEncrypt or encode operation indicator.\n"              +
                  "\t\r-d  --decrypt-decode  \rDecrypt or decode operation indicator.\n"              +
                  "\t\r-2  --b32-hex         \rFor B32 mode. Uses The extended hex alphabet.\n"       +
                  "\t\r-8  --no-rfc4648      \rFor B32 and B64 modes. Coding without the RFC4648"     +
                  "\n\t\t\t      specification.\n\n"                                                  +
                  "\t\r-1  --base-code       \rCustom characters to coding in BaseN without the"      +
                  "\n\t\t\t      RFC4648 specification. The length must be equal"                     +
                  "\n\t\t\t      or greater than the specified number of base.\n\n"                   +
                  "\t\r-6  --base-line-wrap  \rNumber of characters to adjust the lines for"          +
                  "\n\t\t\t      BaseN mode. The value should be in increments of"                    +
                  "\n\t\t\t      8 characters with B2, 6 characters with B3, 4"                       +
                  "\n\t\t\t      characters from B4 to B6 (or B64 with RFC4648),"                     +
                  "\n\t\t\t      3 characters from B7 to B15, and 2 characters"                       +
                  "\n\t\t\t      from B16 to B64 (without RFC4648). The maximum"                      +
                  "\n\t\t\t      value is 255 from B7 to B15 and 256 for all"                         +
                  "\n\t\t\t      others.\n\n"                                                         +
                  "\t\r-5  --rounds          \rFor RC5, SALSA20, and CHACHA the number of rounds"     +
                  "\n\t\t\t      should be a integer value (20 by default).\n\n"                      +  
                  "\t\r-4  --rc5-64b         \rFor RC5 mode. Uses a 64 bits word.\n"                  +
                  "\t\r-3  --vmpc-ksa3       \rFor VMPC mode. Uses the Key Scheduling Algorithm.\n"   +
                  "\t\r-x  --max-buffer-size \rMaximum buffer size in bytes for read and write."      +
                  "\n\t\t\t      Modes: All symmetric ciphers and PGP. The default"                   +
                  "\n\t\t\t      value is 1024.\n\n"                                                  +
                  "\t\r-k  --key             \rThe key characters should have a length of the"        +
                  "\n\t\t\t      key size divided by 8. It must be accompanied by"                    +
                  "\n\t\t\t      the initial vector in the subject terms for that"                    +
                  "\n\t\t\t      modifier. This option is prioritized over hash,"                     +
                  "\n\t\t\t      password, salt, and iterations. Modes: All"                          +
                  "\n\t\t\t      symmetric ciphers. This modifier supports"                           +
                  "\n\t\t\t      hexadecimal byte representations by the escape"                      +
                  "\n\t\t\t      characters \\x (two-digit) and \\u for Unicode"                      +
                  "\n\t\t\t      (four-digit).\n\n"                                                   +
                  "\t\r-i  --initial-vector  \rNeeds to be 16 characters for AES, 3DES, DES,"         +
                  "\n\t\t\t      RC2, 3FISH, and MARS. SALSA20 requires exactly 8"                    +
                  "\n\t\t\t      characters. The RIJNDAEL long must be equal to"                      +
                  "\n\t\t\t      the block size divided by 8. With VMPC the value"                    +
                  "\n\t\t\t      should be between 1 and 768 depending on the"                        +
                  "\n\t\t\t      block size. This modifier supports hexadecimal"                      +
                  "\n\t\t\t      byte representations by the escape characters \\x"                   +
                  "\n\t\t\t      (two-digit) and \\u for Unicode (four-digit).\n\n"                   +
                  "\t\r-p  --password        \rWord, phrase or file. Modes: All symmetric"            +
                  "\n\t\t\t      ciphers and PGP private key or x509 certificates"                    +
                  "\n\t\t\t      for RSA or PGP with encrypted private key (*.pfx"                    +
                  "\n\t\t\t      or *.pem). This modifier supports hexadecimal"                       +
                  "\n\t\t\t      byte representations by the escape characters"                       +
                  "\n\t\t\t      \\x (two-digit) and \\u for Unicode (four-digit)"                    +
                  "\n\t\t\t      with symmetric ciphers.\n\n"                                         +
                  "\t\r-s  --salt            \rAt least 8 characters. Modes: All symmetric"           +
                  "\n\t\t\t      ciphers.\n\n"                                                        +
                  "\t\r-h  --hash            \rHash algorithm. Modes: DIGEST, CHECKSUM, all"          +
                  "\n\t\t\t      symmetric ciphers, ECIES, DLIES, and ELGAMAL with"                   +
                  "\n\t\t\t      OAEP (ELGAMAL only support MD5 and SHA-2 hashes)."                   +
                  "\n\t\t\t      Use the help combined with this modifier to list"                    +
                  "\n\t\t\t      or for more info.\n\n"                                               +
                  "\t\r-t  --iterations      \rNumber of iterations to do. Range from 1 to"           +
                  "\n\t\t\t      2,147,483,647 (1000 by default). Bear in mind"                       +
                  "\n\t\t\t      that a greater number of iterations implies a"                       +
                  "\n\t\t\t      slower process. Modes: All symmetric ciphers.\n\n"                   +
                  "\t\r-c  --cipher-mode     \rCBC (Cipher Block Chianing) by default for all"        +
                  "\n\t\t\t      symmetric block ciphers. The cipher modes CFB"                       +
                  "\n\t\t\t      (Cipher feedback), or OFB (Output feedback) are"                     +
                  "\n\t\t\t      valid for all block ciphers except AES. Other"                       +
                  "\n\t\t\t      cipher modes like ECB (Electronic Code Book),"                       +
                  "\n\t\t\t      or CTS (Cipher Text Stealing) are only valid for"                    +
                  "\n\t\t\t      RC2, 3DES, DES, MARS, AES, and RIJNDAEL with iv.\n\n"                +
                  "\t\r-n  --padding         \rANSIX923, ZEROS, ISO10126, or PKCS7 (by default)."     +
                  "\n\t\t\t      Modes: 3FISH, AES, 3DES, DES, RC2, and RIJNDAEL."                    +
                  "\n\t\t\t      MARS only support PKCS7, and the others block"                       +
                  "\n\t\t\t      ciphers also support ISO7816 or TBC but no ZEROS"                    +
                  "\n\t\t\t      padding mode. RSA and ELGAMAL support PKCS1 (by"                     +
                  "\n\t\t\t      default) and ISO9796D1 for RSA with Bouncy"                          +
                  "\n\t\t\t      Castle.\n\n"                                                         +
                  "\t\r-r  --random-gen      \rRandom password, salt, and initial vector"             +
                  "\n\t\t\t      generator. Modes: All symmetric ciphers.\n\n"                        +
                  "\t\r-l  --block-size      \rThe RIJNDAEL legal values: 128, 160, 192, 224,"        +
                  "\n\t\t\t      and 256 (by default). The HC legal values: 128"                      +
                  "\n\t\t\t      (by default) or 256. For VMPC the value must be"                     +
                  "\n\t\t\t      between 8 and 6144 bits in increments of 8 bits"                     +
                  "\n\t\t\t      (256 by default).\n\n"                                               +
                  "\t\r-z  --feedback-size   \rFor RIJNDAEL only. The feedback size determines"       +
                  "\n\t\t\t      the amount of data that is fed back to successive"                   +
                  "\n\t\t\t      encryption or decryption operations. The feedback"                   +
                  "\n\t\t\t      size cannot be greater than the block size.\n\n"                     +
                  "\t\r-y  --key-size        \rKey size in bits. Use the help combined with this"     +
                  "\n\t\t\t      modifier to list or for more info.\n\n"                              +
                  "\t\r-g  --key-pair-gen    \rKey pair generator. Modes: ECIES, DLIES, ELGAMAL,"     +
                  "\n\t\t\t      NACCACHE, RSA, and PGP. The public and private"                      +
                  "\n\t\t\t      key file names will be required.\n\n"                                +
                  "\t\r-b  --public-key      \rPublic key file name. Modes: ECIES, DLIES, RSA,"       +
                  "\n\t\t\t      PGP, NACCACHE, and ELGAMAL.\n\n"                                     +
                  "\t\r-v  --private-key     \rPrivate key file name. Modes: ECIES, DLIES, RSA,"      +
                  "\n\t\t\t      PGP, NACCACHE, and ELGAMAL.\n\n"                                     +
                  "\t\r-9  --x509-file       \rX509 certificate file name. Modes: RSA and PGP.\n"     +
                  "\t\r-0  --x509-name       \rX509 common name in the certificate store, Modes:"     +
                  "\n\t\t\t      RSA and PGP.\n\n"                                                    +
                  "\t\r-f  --format          \rFor RSA and PGP. XML or BLOB (by default for RSA)"     +
                  "\n\t\t\t      and ARMORED for PGP.\n\n"                                            +
                  "\t\r-a  --oaep            \rFor ELGAMAL and RSA. Microsoft CryptoAPI only"         +
                  "\n\t\t\t      supports OAEP since Windows XP for RSA.\n\n"                         +
                  "\t\r-q  --pgp-cipher      \rSymmetric cipher for PGP encryption: AES128,"          +
                  "\n\t\t\t      AES192, AES256 (by default), BLOWFISH, 2FISH,"                       +
                  "\n\t\t\t      CAST5, DES, 3DES, IDEA, CAMELLIA128, CAMELLIA192,"                   +
                  "\n\t\t\t      CAMELLIA256, and SAFER.\n\n"                                         +
                  "\t\r-u  --crossbreeding   \rFor RSA, ELGAMAL, and PGP. It allows use either"       +
                  "\n\t\t\t      keys from RSA to PGP and PGP to RSA or ELGAMAL"                      +
                  "\n\t\t\t      to PGP and PGP to ELGAMAL.\n\n"                                      +
                  "\t\r-j  --tell-apart      \rSets customized password and salt for each file"       +
                  "\n\t\t\t      in batch process with symmetric ciphers.\n\n"                        +
                  "\t\r-o  --output          \rOutput file name or path.\n"                           +
                  "\t\r-w  --overwrite       \rOverwrites the existing output file(s) without"        +
                  "\n\t\t\t      asking.\n\n"                                                         +
                  "\t\r-7  --io-options      \rInput and output options. Use the help combined"       +
                  "\n\t\t\t      with this modifier to list or for more info.\n\n"                    +
                  "\t\r--export              \rFor RSA, PGP, and ELGAMAL. Exports certificates"       +
                  "\n\t\t\t      and keys. Use the help combined with this"                           +
                  "\n\t\t\t      modifier to list or for more info.\n\n"                              +
                  "\t\r--encoding            \rCharacter encoding for password, key and initial"      +
                  "\n\t\t\t      vector with symmetric ciphers. The available"                        +
                  "\n\t\t\t      encodings are: ASCII (by default), UNICODE-LE,"                      +
                  "\n\t\t\t      UNICODE-BE, UTF-7, UTF-8, and UTF-32.\n\n"                           +
                  "\t\r--rsa-bouncy-castle   \rUses the Bouncy Castle for RSA mode (Key pair"         +
                  "\n\t\t\t      generation, encription, and decryption).\n\n"                        +
                  "\t\r--without-iv-tweak    \rWithout tweak or initial vector if possible for"       +
                  "\n\t\t\t      symmetric block ciphers.\n\n"                                        +
                  "\t\r--gost-box            \rSpecifies s-box for GOST mode. The available"          +
                  "\n\t\t\t      s-boxes are: DEFAULT, E-TEST, E-A, E-B, E-C, E-D,"                   +
                  "\n\t\t\t      D-TEST, D-A, IV, or empty string for nothing at"                     +
                  "\n\t\t\t      all.\n\n"                                                            +
                  "\t\r--pgp-id              \rIdentity for PGP key pair.\n"                          +
                  "\t\r--pgp-sha1            \rUses SHA1 with PGP key pair for checksum.\n"           +
                  "\t\r--pgp-algorithm       \rPublic and private keys algorithm for PGP mode."       +
                  "\n\t\t\t      The available algorithms are: RSA (by default),"                     +
                  "\n\t\t\t      and ELGAMAL.\n\n"                                                    +
                  "\t\r--pgp-master          \rMaster key pair type for PGP. The available"           +
                  "\n\t\t\t      masters are: DSA (By default for ELGAMAL), ECDSA,"                   +
                  "\n\t\t\t      and ECDH.\n\n"                                                       +
                  "\t\r--pgp-sign            \rSignature for PGP encryption. The private key or"      +
                  "\n\t\t\t      certificate will be required.\n\n"                                   +
                  "\t\r--ies-cipher          \rSymmetric cipher for ECIES and DLIES modes: AES"       +
                  "\n\t\t\t      (by default), RIJNDAEL, SERPENT, TNEPRES,"                           +
                  "\n\t\t\t      CAMELLIA, GOST, 2FISH, 3FISH, DES, 3DES, RC2,"                       +
                  "\n\t\t\t      RC5, RC6, SKIPJACK, BLOWFISH, CAST5, CAST6, TEA,"                    +
                  "\n\t\t\t      XTEA, SEED, IDEA, NOEKEON, or empty string for"                      +
                  "\n\t\t\t      nothing at all.\n\n"                                                 +
                  "\t\r--curve               \rSpecifies a curve name for ECIES mode and PGP"         +
                  "\n\t\t\t      with ECDSA or ECDH master keys.\n\n"                                 +
                  "\t\r--curve-store         \rSpecifies a store of curves for ECIES mode and"        +
                  "\n\t\t\t      PGP with ECDSA or ECDH master keys. The stores"                      +
                  "\n\t\t\t      curve are: CUSTOM, TELETRUST, NIST, ANSSI, X962,"                    +
                  "\n\t\t\t      GOST, and SEC (by default).\n\n"                                     +
                  "\t\r--show-store-curves   \rShows the available curves in the specified"           +
                  "\n\t\t\t      store.\n\n"                                                          +
                  "\t\r--raise-pwd-exception \rRaises exception for incorrect password or salt.\n"    +
                  "\t\r--inhibit-errors      \rContinue even with errors if possible in batch"        +
                  "\n\t\t\t      process.\n\n"                                                        +
                  "\t\r--inhibit-esc-chars   \rDoes not process hexadecimal byte representations"     +
                  "\n\t\t\t      by the escape characters \\x or \\u for Unicode.\n\n"                +
                  "\t\r--inhibit-delimiter   \rDoes not process semicolon as a path delimiter.\n"     +
                  "\t\r--input-notes         \rShows informative notes of input data.\n"              +
                  "\t\r--examples            \rShows command line examples for specified mode.\n"     +
                  "\t\r--help                \rShows usage info. This modifier can be combined"       +
                  "\n\t\t\t      with others from behind or ahead for more info.\n"
                , new ConsoleColor[]
                  {
                        ConsoleColor.Yellow
                      , ConsoleColor.Gray

                      , ConsoleColor.Yellow

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray

                      , ConsoleColor.White
                      , ConsoleColor.Gray
                  }
            );
        }

        //----------------------------------------------------------------------------------

        private static void ShowHelp (string cmd)
        {
            string s0 = "\n\t- ";
            string s1 = " (Blue Midnight Wish)";
            string s2 = " (Radio Gatun)";
            string s3 = " *";

            Program.ShowBanner();
            switch (cmd.ToLower())
            { 
                case MOD_SHORT_MODE:
                case MOD_LONG_MODE:
                    Messenger.Print
                    (
                          "\n Coders:\r\n"                                                      +
                          "\n\t- Bn (Base n, Where n must be a number from 2 to 64)\n\n"        +
                          "\r Symmetric Block Ciphers:\r\n"                                     +
                          "\n\t- RIJNDAEL"                                                      +
                          "\n\t- AES (Advanced Encryption Standard)"                            +
                          "\n\t- 3DES (Triple Data Encryption Standard)"                        +
                          "\n\t- DES (Data Encryption Standard)"                                +
                          "\n\t- RC2 (Rivest Cipher 2)"                                         +
                          "\n\t- RC5 (Rivest Cipher 5)"                                         +
                          "\n\t- RC6 (Rivest Cipher 6)"                                         +
                          "\n\t- MARS"                                                          +
                          "\n\t- SERPENT"                                                       +
                          "\n\t- TNEPRES"                                                       + 
                          "\n\t- 2FISH (Twofish)"                                               +
                          "\n\t- 3FISH (Threefish)"                                             +
                          "\n\t- BLOWFISH"                                                      +
                          "\n\t- CAST5"                                                         +
                          "\n\t- CAST6"                                                         +
                          "\n\t- IDEA (International Data Encryption Algorithm)"                +
                          "\n\t- GOST (The Government Standard of the USSR 28147)"              +
                          "\n\t- NOEKEON"                                                       +
                          "\n\t- SEED"                                                          +
                          "\n\t- TEA"                                                           +
                          "\n\t- XTEA"                                                          +
                          "\n\t- SKIPJACK\n\n"                                                  +
                          "\r Symmetric Stream Ciphers:\r\n"                                    +
                          "\n\t- RC4 (Rivest Cipher 4)"                                         +
                          "\n\t- ISAAC"                                                         +
                          "\n\t- SALSA20"                                                       +
                          "\n\t- XSALSA20"                                                      +
                          "\n\t- CHACHA"                                                        +
                          "\n\t- VMPC (Variably Modified Permutation Composition)"              +
                          "\n\t- HC (Hongjun Cipher)\n\n"                                       +
                          "\r Asymmetric Ciphers:\r\n"                                          +
                          "\n\t- RSA (Rivest, Shamir and Adleman)"                              +
                          "\n\t- PGP (Pretty Good Privacy, Open)"                               +
                          "\n\t- ELGAMAL"                                                       +
                          "\n\t- NACCACHE\n\n"                                                  +
                          "\r Hybrids:\r\n"                                                     +
                          "\n\t- ECIES (Elliptic Curve Integrated Encryption Scheme)"           +
                          "\n\t- DLIES (Discrete Logarithm Integrated Encryption Scheme)\n\n"   +
                          "\r Others:\r\n"                                                      +
                          "\n\t- DIGEST (Digest file mode)"                                     +
                          "\n\t- CHECKSUM (Checksum file mode)\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.Yellow
                              , ConsoleColor.Gray
                              
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                   );
                   break;

                case MOD_SHORT_HASH:
                case MOD_LONG_HASH:
                    Messenger.Print
                    (
                          "\n SHA-3 (Candidates):\r\n"                                      +     
                          s0 + HASH_BLAKE224                                                +
                          s0 + HASH_BLAKE256                                                +
                          s0 + HASH_BLAKE384                                                +
                          s0 + HASH_BLAKE512                                                +
                          s0 + HASH_BMW224                                                  + s1 +
                          s0 + HASH_BMW256                                                  + s1 +
                          s0 + HASH_BMW384                                                  + s1 +
                          s0 + HASH_BMW512                                                  + s1 +
                          s0 + HASH_CUBE224                                                 +
                          s0 + HASH_CUBE256                                                 +
                          s0 + HASH_CUBE384                                                 +
                          s0 + HASH_CUBE512                                                 +
                          s0 + HASH_ECHO224                                                 +
                          s0 + HASH_ECHO256                                                 +
                          s0 + HASH_ECHO384                                                 +
                          s0 + HASH_ECHO512                                                 +
                          s0 + HASH_FUGUE224                                                +
                          s0 + HASH_FUGUE256                                                +
                          s0 + HASH_FUGUE384                                                +
                          s0 + HASH_FUGUE512                                                +
                          s0 + HASH_GROESTL224                                              +
                          s0 + HASH_GROESTL256                                              +
                          s0 + HASH_GROESTL384                                              +
                          s0 + HASH_GROESTL512                                              +
                          s0 + HASH_HAMSI224                                                +
                          s0 + HASH_HAMSI256                                                +
                          s0 + HASH_HAMSI384                                                +
                          s0 + HASH_HAMSI512                                                +
                          s0 + HASH_JH224                                                   +
                          s0 + HASH_JH256                                                   +
                          s0 + HASH_JH384                                                   +
                          s0 + HASH_JH512                                                   +
                          s0 + HASH_KECCAK224                                               + s3 +
                          s0 + HASH_KECCAK256                                               + s3 +
                          s0 + HASH_KECCAK384                                               + s3 +
                          s0 + HASH_KECCAK512                                               + s3 +
                          s0 + HASH_LUFFA224                                                +
                          s0 + HASH_LUFFA256                                                +
                          s0 + HASH_LUFFA384                                                +
                          s0 + HASH_LUFFA512                                                +
                          s0 + HASH_SHABAL224                                               +
                          s0 + HASH_SHABAL256                                               +
                          s0 + HASH_SHABAL384                                               +
                          s0 + HASH_SHABAL512                                               +
                          s0 + HASH_SHAVITE_224                                             +
                          s0 + HASH_SHAVITE_256                                             +
                          s0 + HASH_SHAVITE_384                                             +
                          s0 + HASH_SHAVITE_512                                             +
                          s0 + HASH_SIMD224                                                 +
                          s0 + HASH_SIMD256                                                 +
                          s0 + HASH_SIMD384                                                 +
                          s0 + HASH_SIMD512                                                 +
                          s0 + HASH_SKEIN224                                                +
                          s0 + HASH_SKEIN256                                                + s3 +
                          s0 + HASH_SKEIN384                                                +
                          s0 + HASH_SKEIN512                                                + s3 +
                          "\n\n \rSHA-2:\r\n"                                               +
                          s0 + HASH_SHA224                                                  + s3                   +
                          s0 + HASH_SHA256                                                  + s3                   +
                          s0 + HASH_SHA384                                                  + s3                   +
                          s0 + HASH_SHA512                                                  + s3 + " (By default)" +
                          "\n\n \rSHA (Old):\r\n"                                           +
                          s0 + HASH_SHA1                                                    + s3 +
                          s0 + HASH_SHA0                                                    +
                          "\n\n \rMD (Message Digest):\r\n"                                 +
                          s0 + HASH_MD2                                                     + s3 +
                          s0 + HASH_MD4                                                     + s3 +
                          s0 + HASH_MD5                                                     + s3 +
                          "\n\n \rRace Integrity Primitives Evaluation Message Digest:\r\n" +
                          s0 + HASH_RIPEMD                                                  +
                          s0 + HASH_RIPEMD128                                               + s3 +
                          s0 + HASH_RIPEMD160                                               + s3 +
                          s0 + HASH_RIPEMD256                                               + s3 +
                          s0 + HASH_RIPEMD320                                               + s3 +
                          "\n\n \rOthers (32-bits):\r\n"                                    +
                          s0 + HASH_AP                                                      +
                          s0 + HASH_BERNSTEIN                                               +
                          s0 + HASH_BERNSTEIN1                                              +
                          s0 + HASH_BKDR                                                    +
                          s0 + HASH_DEK                                                     +
                          s0 + HASH_DJB                                                     +
                          s0 + HASH_DOTNET                                                  +
                          s0 + HASH_ELF                                                     +
                          s0 + HASH_FNV                                                     +
                          s0 + HASH_FNV1A                                                   +
                          s0 + HASH_JENKINS3                                                +
                          s0 + HASH_JS                                                      +
                          s0 + HASH_MURMUR2                                                 +
                          s0 + HASH_MURMUR3                                                 +
                          s0 + HASH_ONEATTIME                                               +
                          s0 + HASH_PJW                                                     +
                          s0 + HASH_ROTATING                                                +
                          s0 + HASH_RS                                                      +
                          s0 + HASH_SDBM                                                    +
                          s0 + HASH_SHIFTANDXOR                                             + " (Shift And Xor)" +
                          s0 + HASH_SUPERFAST                                               +
                          "\n\n \rOthers (64-bits):\r\n"                                    +
                          s0 + HASH_FNV64                                                   +
                          s0 + HASH_FNV1A64                                                 +
                          s0 + HASH_MURMUR2_64                                              +
                          s0 + HASH_SIPHASH                                                 +
                          "\n\n \rOthers (128-bits):\r\n"                                   +
                          s0 + HASH_MURMUR3_128                                             +
                          "\n\n \rOthers:\r\n"                                              +
                          s0 + GOST                                                         +
                          s0 + HASH_GRINDAHL256                                             +
                          s0 + HASH_GRINDAHL512                                             +
                          s0 + HASH_HAS160                                                  +
                          s0 + HASH_HAVAL3_128                                              +
                          s0 + HASH_HAVAL3_160                                              +
                          s0 + HASH_HAVAL3_192                                              +
                          s0 + HASH_HAVAL3_224                                              +
                          s0 + HASH_HAVAL3_256                                              +
                          s0 + HASH_HAVAL4_128                                              +
                          s0 + HASH_HAVAL4_160                                              +
                          s0 + HASH_HAVAL4_192                                              +
                          s0 + HASH_HAVAL4_224                                              +
                          s0 + HASH_HAVAL4_256                                              +
                          s0 + HASH_HAVAL5_128                                              +
                          s0 + HASH_HAVAL5_160                                              +
                          s0 + HASH_HAVAL5_192                                              +
                          s0 + HASH_HAVAL5_224                                              +
                          s0 + HASH_HAVAL5_256                                              +
                          s0 + HASH_PANAMA                                                  +
                          s0 + HASH_RG32                                                    + s2 +
                          s0 + HASH_RG64                                                    + s2 +
                          s0 + HASH_SNEFRU4_128                                             +
                          s0 + HASH_SNEFRU4_256                                             +
                          s0 + HASH_SNEFRU8_128                                             +
                          s0 + HASH_SNEFRU8_256                                             +
                          s0 + HASH_TIGER2                                                  +
                          s0 + HASH_TIGER3_192                                              +
                          s0 + HASH_TIGER4_192                                              +
                          s0 + HASH_WHIRLPOOL                                               + s3 +
                          "\n\n \rChecksum:\r\n"                                            +
                          s0 + HASH_ADLER32                                                 +
                          s0 + HASH_CRC32_IEEE                                              +
                          s0 + HASH_CRC32_CASTAGNOLI                                        +
                          s0 + HASH_CRC32_KOOPMAN                                           +
                          s0 + HASH_CRC32_Q                                                 +
                          s0 + HASH_CRC64_ISO                                               +
                          s0 + HASH_CRC64_ECMA                                              +
                          "\n\n * Supported for DLIES and ECIES modes.\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                   );
                   break;

                case MOD_SHORT_KEY_SIZE:
                case MOD_LONG_KEY_SIZE:
                   Messenger.Print
                   (
                           "\n >\r RC2, RC5, CAST5, and SKIPJACK supports key sizes from 40 to 128 bits in"        +
                           "\n   increments of 8 bits (128 by default).\n"                                         +
                           "\n \r>\r RC6 supports key sizes from 40 to 256 bits in increments of 8 bits (256 by"   +
                           "\n   default).\n"                                                                      +
                           "\n \r>\r RC4 supports key sizes from 40 to 2048 bits in increments of 8 bits (256 by"  +
                           "\n   default).\n"                                                                      +
                           "\n \r>\r MARS supports key sizes from 128 to 448 bits in increments of 8 bits (256 by" +
                           "\n   default).\n"                                                                      +
                           "\n \r>\r BLOWFISH supports key sizes from 40 to 448 bits in increments of 8 bits (256" +
                           "\n   by default).\n"                                                                   +
                           "\n \r>\r 3FISH supports key sizes of 256, 512, and 1024 bits (256 by default).\n"      +
                           "\n \r>\r CAMELLIA, CAST6, 3DES, AES, 2FISH, SERPENT, TNEPRES, and RIJNDAEL supports"   +
                           "\n   keys of 128, or 192 (by default for 3DES), and 256 bits (by default for"          +
                           "\n   CAST6, AES, 2FISH, SERPENT, TNEPRES, CAMELLIA, and RIJNDAEL).\n"                  +
                           "\n \r>\r SALSA20, CHAHA, and HC supports key sizes of 128 or 256 bits (by default)."   +
                           "\n \r>\r VMPC supports key sizes from 40 to 6144 bits in increments of 8 bits (256 by" +
                           "\n   default).\n"                                                                      +
                           "\n \r>\r ISAAC supports key sizes from 32 to 8192 bits in increments of 8 bits (256"   +
                           "\n   by default).\n"                                                                   +
                           "\n \r>\r NACCACHE and ELGAMAL can be any key size since 128 bits in increments of 8"   +
                           "\n   bits (768 by default). However, a considerably large key can greatly"             +
                           "\n   increase processing time.\n"                                                      +
                           "\n \r>\r RSA and PGP supports key sizes from 384 to 16384 bits in increments of 8"     +
                           "\n   bits if you have Mono or Microsoft Enhanced Cryptographic Provider"               +
                           "\n   installed. It supports key sizes from 384 to 512 bits in increments of 8"         +
                           "\n   bits if you have the Microsoft Base Cryptographic Provider installed. 1024"       +
                           "\n   is the default value for RSA and PGP mode with Mono or Microsoft Enhanced"        +
                           "\n   Cryptographic Provider, and 512 with Microsoft Base Cryptographic"                +
                           "\n   Provider.\n"
                        ,  new ConsoleColor[]
                          {
                                ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                              
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                              
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                   );
                   break;

                case MOD_LONG_EXPORT:
                   Messenger.Print
                   (
                       "\n Certificate to RSA Keys:\n\r"                                                 +
                       "\n\tcrypter -m rsa -9 file.cer --export -b pubic.key"                            +
                       "\n\tcrypter -m rsa -9 file.pfx --export -b pubic.key -v private.key"             +
                       "\n\tcrypter -m rsa -9 file.pfx -p \"my password\" --export -b pubic.key \\\n"    +
                       "\t        -v private.key\n"                                                      +
                       "\n\r RSA to PGP Keys:\n\r"                                                       +
                       "\n\tcrypter -m rsa -b rsa-public.key --export -b pgp-pubic.key"                  +
                       "\n\tcrypter -m rsa -v rsa-private.key --export -b pgp-pubic.key \\\n"            +
                       "\t        -v pgp-private.key --pgp-sha1\n"                                       +
                       "\n\tcrypter -m rsa -v rsa-private.key --export -b pgp-pubic.key \\\n"            +
                       "\t        -v pgp-private.key -p \"my private key password\" --pgp-sha1\n"        +
                       "\n\r Certificate to PGP Keys:\n\r"                                               +
                       "\n\tcrypter -m pgp -9 file.cer --export -b pubic.key"                            +
                       "\n\tcrypter -m pgp -9 file.pfx --export -b pubic.key -v private.key"             +
                       "\n\tcrypter -m pgp -9 file.pfx -p \"my certificate password\" --export \\\n"     +
                       "\t        -b pubic.key -v private.key -p \"my private key password\" \\\n"       +
                       "\t        --pgp-sha1\n"                                                          +
                       "\n\r PGP to RSA Keys:\n\r"                                                       +
                       "\n\tcrypter -m pgp -b pgp-public.key --export -b rsa-pubic.key"                  +
                       "\n\tcrypter -m pgp -v pgp-private.key --export -b rsa-pubic.key \\\n"            +
                       "\t        -v rsa-private.key\n"                                                  +
                       "\n\tcrypter -m pgp -v pgp-private.key -p \"my password\" --export \\\n"          +
                       "\t        -b rsa-pubic.key -v rsa-private.key\n"                                 +
                       "\n\r PGP to ELGAMAL Keys:\n\r"                                                   +
                       "\n\tcrypter -m pgp --pgp-algorithm elgamal -b pgp-public.key --export \\\n"      +
                       "\t        -b elgamal-pubic.key\n"                                                +
                       "\n\tcrypter -m pgp --pgp-algorithm elgamal -v pgp-private.key --export \\\n"     +
                       "\t        -v elgamal-private.key\n"                                              +
                       "\n\tcrypter -m pgp --pgp-algorithm elgamal -v pgp-private.key \\\n"              +
                       "\t        -p \"my password\" --export -v elgamal-private.key\n"                  +
                       "\n\tcrypter -m pgp --pgp-algorithm elgamal -b pgp-public.key \\\n"               +
                       "\t        -v pgp-private.key -p \"my password\" --export \\\n"                   +
                       "\t        -b elgamal-pubic.key -v elgamal-private.key\n"                         +
                       "\n\r ELGAMAL to PGP Keys:\n\r"                                                   +
                       "\n\tcrypter -m elgamal -b elgamal-public.key -v elgamal-private.key \\\n "       +
                       "\t        --export -b pgp-public.key -v pgp-private.key \\\n"                    +
                       "\t        -p \"my password\" --pgp-sha1\n"
                       , new ConsoleColor[]
                         {
                              ConsoleColor.Yellow
                            , ConsoleColor.Gray

                            , ConsoleColor.Yellow
                            , ConsoleColor.Gray

                            , ConsoleColor.Yellow
                            , ConsoleColor.Gray

                            , ConsoleColor.Yellow
                            , ConsoleColor.Gray

                            , ConsoleColor.Yellow
                            , ConsoleColor.Gray

                            , ConsoleColor.Yellow
                            , ConsoleColor.Gray
                         }
                   );
                   break;

                case MOD_SHORT_IO_OPTIONS:
                case MOD_LONG_IO_OPTIONS:
                   Messenger.Print
                   (
                       "\n Input output options separated by commas:\n\r"          +
                       "\n\t- BASIC (by default): Basic wildcards patterns."       +
                       "\n\t- GLOB: Globbing patterns."                            +
                       "\n\t- EXTGLOB: Extended globbing patterns."                +
                       "\n\t- REGEX: Regular expressions patterns."                +
                       "\n\t- UNIGNORE-CASE: Case sensitive."                      +
                       "\n\t- RECURSIVELY: Search for patterns recursively."       +
                       "\n\t- REVERSE: Search for patterns inversely.\n"           +
                       "\n\r Character escape (for glob, extglob, and regex):\n\r" +
                       "\n\t- Windows: /"                                          +
                       "\n\t- Others:  \\\n"                                       +
                       "\n\r Examples:\n\r"                                        +
                       "\n\tcryprer -m aes -e \"/my path/my file?.*\""             +
                       "\n\tcryprer -m aes -7 extglob,unignore-case -e \\"         +
                       "\n\t        \"/my path/+([my[:space:]])file[0-9].*\"\n"
                       , new ConsoleColor[]
                         {
                              ConsoleColor.Yellow
                            , ConsoleColor.Gray

                            , ConsoleColor.Yellow
                            , ConsoleColor.Gray
                            , ConsoleColor.Yellow
                            , ConsoleColor.Gray
                         }
                   );
                   break;

                default:
                   throw new Exception("Unsupported modifier with combined help!");
            }

            Environment.Exit(0);
        }

        //----------------------------------------------------------------------------------

        private static void ShowExamples (string mode)
        {
            Program.ShowBanner();

            byte   b, n = 128;
            string s0 = "\n\n <{0}>\n"                                      +
                        "\n \rEncode:\r\n\n"                                +
                        "\tcrypter -o file.{1} -m {1} -e file.txt\n"        +
                        "\tcrypter -o file.{1} -m {1} -6 {2} -e file.txt\n" +
                        "\tcrypter -o file.{1} -m {1} -1 {3} -e file.txt\n" +
                        "\n \rDecode:\r\n\n"                                +
                        "\tcrypter -o file.txt -m {1} -d file.{1}\n"        +
                        "\tcrypter -o file.txt -m {1} -1 {3} -d file.{1}\n";

            string s1 = "\n\n <{0}>\n"                                      +
                        "\n \rEncode:\r\n\n"                                +
                        "\tcrypter -o file.{1} -m {1} -e file.txt\n"        +
                        "\tcrypter -o file.{1} -m {1} -6 {2} -e file.txt\n" +
                        "\tcrypter -o file.{1} -m {1} -8 -e file.txt\n"     +
                        "\tcrypter -o file.{1} -m {1} -1 {3} -e file.txt\n" +
                        "\n \rDecode:\r\n\n"                                +
                        "\tcrypter -o file.txt -m {1} -d file.{1}\n"        +
                        "\tcrypter -o file.txt -m {1} -8 -d file.{1}\n"     +
                        "\tcrypter -o file.txt -m {1} -1 {3} -d file.{1}\n";


            string s2 = "\n\n <{0}>\n"                                                                  +
                        "\n \rEncryption:\r\n\n"                                                        +
                        "\tcrypter -o file.{1} -m {2} -e file.bin\n"                                    +
                        "\tcrypter -o file.{1} -m {2} -p \"my password\" -s \"my salt8\" -e file.bin\n" +
                        "\tcrypter -o file.{1} -m {2} -p file:\"my password file.txt\" -e file.bin\n"   +
                        "\tcrypter -o file.{1} -m {2} -s \"\" -h sha1 -e file.bin\n"                    +
                        "\tcrypter -o file.{1} -m {2} -y 128 -k 1234567890123456 \\\n"                  +
                        "\t        -i 6543210987654321 -e file.bin\n"                                   +
                        "\n \rDecryption:\r\n\n"                                                        +
                        "\tcrypter -o file.bin -m {2} -d file.{1}\n"                                    +
                        "\tcrypter -o file.bin -m {2} -p \"my password\" -s \"my salt8\" -d file.{1}\n" +
                        "\tcrypter -o file.bin -m {2} -p file:\"my password file.txt\" -d file.{1}\n"   +
                        "\tcrypter -o file.bin -m {2} -s \"\" -h sha1 -d file.{1}\n"                    +
                        "\tcrypter -o file.bin -m {2} -y 128 -k 1234567890123456 \\\n"                  +
                        "\t        -i 6543210987654321 -d file.{1}\n";

            string s3 = "-y 128 ";
            string s4 = "\n\n <{0}>\n"                                                          +
                        "\n \rEncryption:\r\n\n"                                                +
                        "\tcrypter -o file.{1} -m {2} -e file.bin\n"                            +
                        "\tcrypter -o file.{1} -m {2} {3}-k 1234567890123456 -e file.bin\n"     +
                        "\tcrypter -o file.{1} -m {2} -s \"\" -h sha1 -e file.bin\n"            +
                        "\tcrypter -o file.{1} -m {2} -p \"my password\" -s \"my salt8\" \\\n"  +
                        "\t        -e file.bin\n\n"                                             +
                        "\tcrypter -o file.{1} -m {2} -p file:\"my password file.txt\" \\\n"    +
                        "\t        -e file.bin\n"                                               +
                        "\n \rDecryption:\r\n\n"                                                +
                        "\tcrypter -o file.bin -m {2} -d file.{1}\n"                            +
                        "\tcrypter -o file.bin -m {2} {3}-k 1234567890123456 -d file.{1}\n"     +
                        "\tcrypter -o file.bin -m {2} -s \"\" -h sha1 -d file.{1}\n"            +
                        "\tcrypter -o file.bin -m {2} -p \"my password\" -s \"my salt8\" \\\n"  +
                        "\t        -d file.{1}\n\n"                                             +
                        "\tcrypter -o file.bin -m {2} -p file:\"my password file.txt\" \\\n"    +
                        "\t        -d file.{1}\n";

            switch (mode = mode.ToUpper())
            {
                case B7:
                case B8:
                case B9:
                case B10:
                case B11:
                case B12:
                case B13:
                case B14:
                case B15:
                    n = 126;
                    goto case B64;

                case B2:
                case B3:
                case B4:
                case B5:
                case B6:
                case B16:
                case B17:
                case B18:
                case B19:
                case B20:
                case B21:
                case B22:
                case B23:
                case B24:
                case B25:
                case B26:
                case B27:
                case B28:
                case B29:
                case B30:
                case B31:
                case B32:
                case B33:
                case B34:
                case B35:
                case B36:
                case B37:
                case B38:
                case B39:
                case B40:
                case B41:
                case B42:
                case B43:
                case B44:
                case B45:
                case B46:
                case B47:
                case B48:
                case B49:
                case B50:
                case B51:
                case B52:
                case B53:
                case B54:
                case B55:
                case B56:
                case B57:
                case B58:
                case B59:
                case B60:
                case B61:
                case B62:
                case B63:
                case B64:
                    s2 = CODE.Substring(0, b = byte.Parse(mode.Substring(1)));

                    if (b > 28)
                        s2 = s2.Insert(28, " \\\n\t        ");

                    Messenger.Print
                    (
                           string.Format(mode == B32 || mode == B64 ? s1 : s0, "BASE-" + b, mode.ToLower(), n, s2)
                        ,  new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case DIGEST:
                    Messenger.Print
                    (
                          "\n\n <DIGEST>\r\n\n"                                +
                          "\tcrypter -m digest file.bin\n"                     +
                          "\tcrypter -m digest -h sha256 file.bin\n"           +
                          "\tcrypter -o file.txt -m digest -h md5 file.bin\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case CHECKSUM:
                    Messenger.Print
                    (
                          "\n\n <CHECKSUM>\r\n\n"                                       +
                          "\tcrypter -m checksum -h adler32 file.bin\n"                 +
                          "\tcrypter -o file.txt -m checksum -h crc32-ieee file.bin\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case AES:
                    Messenger.Print
                    (
                          string.Format(s2, AES, AES.ToLower(), AES.ToLower())
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case RIJNDAEL:
                    Messenger.Print
                    (
                          "\n\n <RIJNDAEL>\n"                                                         + 
                          "\n \rEncryption:\r\n\n"                                                    +
                          "\tcrypter -o file.rij -m rijndael -e file.bin\n"                           +
                          "\tcrypter -o file.rij -m rijndael -s \"\" -h sha1 -e file.bin\n"           +
                          "\tcrypter -o file.rij -m rijndael -y 128 -l 128 -k 1234567890123456 \\\n"  +
                          "\t        -i 6543210987654321 -e file.bin\n"                               +
                          "\n \rDecryption:\r\n\n"                                                    +
                          "\tcrypter -o file.bin -m rijndael -d file.rij\n"                           +
                          "\tcrypter -o file.bin -m rijndael -s \"\" -h sha1 -d file.rij\n"           +
                          "\tcrypter -o file.bin -m rijndael -y 128 -l 128 -k 1234567890123456 \\\n"  +
                          "\t        -i 6543210987654321 -d file.rij\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case TDES:
                    Messenger.Print
                    (
                          string.Format(s2, "TRIPLE-DES", TDES.ToLower(), TDES.ToLower())
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case DES:
                    Messenger.Print
                    (
                          "\n\n <DES>\n"                                                                  +
                          "\n \rEncryption:\r\n\n"                                                        +
                          "\tcrypter -o file.des -m des -e file.bin\n"                                    +
                          "\tcrypter -o file.des -m des -p \"my password\" -s \"my salt8\" -e file.bin\n" +
                          "\tcrypter -o file.des -m des -p file:\"my password file.txt\" -e file.bin\n"   +
                          "\tcrypter -o file.des -m des -s \"\" -h sha1 -e file.bin\n"                    +
                          "\tcrypter -o file.des -m des -k 12345678 -i 87654321 -e file.bin\n"            +
                          "\n \rDecryption:\r\n\n"                                                        +
                          "\tcrypter -o file.bin -m des -d file.des\n"                                    +
                          "\tcrypter -o file.bin -m des -p \"my password\" -s \"my salt8\" -d file.des\n" +
                          "\tcrypter -o file.bin -m des -p file:\"my password file.txt\" -d file.des\n"   +
                          "\tcrypter -o file.bin -m des -s \"\" -h sha1 -d file.des\n"                    +
                          "\tcrypter -o file.bin -m des -k 12345678 -i 87654321 -d file.des\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case MARS:
                    Messenger.Print
                    (
                          string.Format(s2, MARS, MARS.Substring(0, 3).ToLower(), MARS.ToLower())
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case SALSA20:
                case CHACHA:
                    mode = mode.ToLower();
                    s0   = mode.Substring(0, 3);

                    Messenger.Print
                    (
                          "\n\n <" + mode.ToUpper() + ">\n"                                              + 
                          "\n \rEncryption:\r\n\n"                                                       +
                          "\tcrypter -o file." + s0 + " -m " + mode + " -e file.bin\n"                   +
                          "\tcrypter -o file." + s0 + " -m " + mode + " -s \"\" -h sha1 -e file.bin\n"   +
                          "\tcrypter -o file." + s0 + " -m " + mode + " -y 128 -k 1234567890123456 \\\n" +
                          "\t        -i 87654321 -e file.bin\n"                                          +
                          "\n \rDecryption:\r\n\n"                                                       +
                          "\tcrypter -o file.bin -m " + mode + " -d file." + s0 + "\n"                   +
                          "\tcrypter -o file.bin -m " + mode + " -s \"\" -h sha1 -d file." + s0 + "\n"   +
                          "\tcrypter -o file.bin -m " + mode + " -y 128 -k 1234567890123456 \\\n"        +
                          "\t        -i 87654321 -d file." + s0 + "\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case XSALSA20:
                    Messenger.Print
                    (
                          "\n\n <XSALSA20>\n"                                               +
                          "\n \rEncryption:\r\n\n"                                          +
                          "\tcrypter -o file.x20 -m xsalsa20 -e file.bin\n"                 +
                          "\tcrypter -o file.x20 -m xsalsa20 -s \"\" -h sha1 -e file.bin\n" +
                          "\n \rDecryption:\r\n\n"                                          +
                          "\tcrypter -o file.bin -m xsalsa20 -d file.x20\n"                 +
                          "\tcrypter -o file.bin -m xsalsa20 -s \"\" -h sha1 -d file.x20\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case VMPC:
                    Messenger.Print
                    (
                          "\n\n <VMPC>\n"                                                                 + 
                          "\n \rEncryption:\r\n\n"                                                        +
                          "\tcrypter -o file.vmp -m vmpc -e file.bin\n"                                   +
                          "\tcrypter -o file.vmp -m vmpc -3 -e file.bin\n"                                +
                          "\tcrypter -o file.vmp -m vmpc -s \"\" -h sha1 -e file.bin\n"                   +
                          "\tcrypter -o file.vmp -m vmpc -y 64 -l 64 -k 12345678 -i 87654321 \\\n"        +
                          "\t        -e file.bin\n"                                                       +
                          "\n \rDecryption:\r\n\n"                                                        +
                          "\tcrypter -o file.bin -m vmpc -d file.vmp\n"                                   +
                          "\tcrypter -o file.bin -m vmpc -3 -d file.vmp\n"                                +
                          "\tcrypter -o file.bin -m vmpc -s \"\" -h sha1 -d file.vmp\n"                   +
                          "\tcrypter -o file.bin -m vmpc -y 64 -l 64 -k 12345678 -i 87654321 \\\n"        +
                          "\t        -d file.vmp\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case RC2:
                    Messenger.Print
                    (
                          "\n\n <RC2>\n"                                                                  +
                          "\n \rEncryption:\r\n\n"                                                        +
                          "\tcrypter -o file.rc2 -m rc2 -e file.bin\n"                                    +
                          "\tcrypter -o file.rc2 -m rc2 -p \"my password\" -s \"my salt8\" -e file.bin\n" +
                          "\tcrypter -o file.rc2 -m rc2 -p file:\"my password file.txt\" -e file.bin\n"   +
                          "\tcrypter -o file.rc2 -m rc2 -s \"\" -h sha1 -e file.bin\n"                    +
                          "\tcrypter -o file.rc2 -m rc2 -y 64 -k 12345678 -i 87654321 -e file.bin\n"      +
                          "\n \rDecryption:\r\n\n"                                                        +
                          "\tcrypter -o file.bin -m rc2 -d file.rc2\n"                                    + 
                          "\tcrypter -o file.bin -m rc2 -p \"my password\" -s \"my salt8\" -d file.rc2\n" +
                          "\tcrypter -o file.bin -m rc2 -p file:\"my password file.txt\" -d file.rc2\n"   +
                          "\tcrypter -o file.bin -m rc2 -s \"\" -h sha1 -d file.rc2\n"                    +
                          "\tcrypter -o file.bin -m rc2 -y 64 -k 12345678 -i 87654321 -d file.rc2\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case CAMELLIA:
                    Messenger.Print
                    (
                          string.Format
                          (
                                s4
                              , CAMELLIA
                              , CAMELLIA.Substring(0, 3).ToLower()
                              , CAMELLIA.ToLower()
                              , s3
                          )
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case BLOWFISH:
                    Messenger.Print
                    (
                          string.Format(s4, BLOWFISH, "blf", BLOWFISH.ToLower(), s3)
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case TWOFISH:
                    Messenger.Print
                    (
                          string.Format(s4, "2FISH", "2f", TWOFISH.ToLower(), s3)
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case THREEFISH:
                    Messenger.Print
                    (
                          "\n\n <3FISH>\n"                                                                 +
                          "\n \rEncryption:\r\n\n"                                                         +
                          "\tcrypter -o file.3f -m 3fish -e file.bin\n"                                    +
                          "\tcrypter -o file.3f -m 3fish -p \"my password\" -s \"my salt8\" -e file.bin\n" +
                          "\tcrypter -o file.3f -m 3fish -p file:\"my password file.txt\" -e file.bin\n"   +
                          "\tcrypter -o file.3f -m 3fish -s \"\" -h sha1 -e file.bin\n"                    +
                          "\tcrypter -o file.3f -m 3fish -k 12345678901234567890123456789012 \\\n"         +
                          "\t        -i 6543210987654321 -e file.bin\n"                                    +
                          "\n \rDecryption:\r\n\n"                                                         +
                          "\tcrypter -o file.bin -m 3fish -d file.3f\n"                                    +
                          "\tcrypter -o file.bin -m 3fish -p \"my password\" -s \"my salt8\" -d file.3f\n" +
                          "\tcrypter -o file.bin -m 3fish -p file:\"my password file.txt\" -d file.3f\n"   +
                          "\tcrypter -o file.bin -m 3fish -s \"\" -h sha1 -d file.3f\n"                    +
                          "\tcrypter -o file.bin -m 3fish -k 12345678901234567890123456789012 \\\n"        +
                          "\t        -i 6543210987654321 -d file.3f\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case SERPENT:
                    Messenger.Print
                    (
                          string.Format
                          (
                                s4
                              , SERPENT
                              , SERPENT.Substring(0, 3).ToLower()
                              , SERPENT.ToLower()
                              , s3
                          )
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case TNEPRES:
                    Messenger.Print
                    (
                          string.Format
                          (
                                s4
                              , TNEPRES
                              , TNEPRES.Substring(0, 3).ToLower()
                              , TNEPRES.ToLower()
                              , s3
                          )
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case CAST5:
                    Messenger.Print
                    (
                          string.Format
                          (
                                s4
                              , CAST5
                              , "c5"
                              , CAST5.ToLower()
                              , s3
                          )
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case CAST6:
                    Messenger.Print
                    (
                          string.Format
                          (
                                s4
                              , CAST6
                              , "c6"
                              , CAST6.ToLower()
                              , s3
                          )
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case IDEA:
                    Messenger.Print
                    (
                          string.Format
                          (
                                s4
                              , IDEA
                              , IDEA.Substring(0, 3).ToLower()
                              , IDEA.ToLower()
                              , string.Empty
                          )
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case NOEKEON:
                    Messenger.Print
                    (
                          string.Format
                          (
                                s4
                              , NOEKEON
                              , NOEKEON.Substring(0, 3).ToLower()
                              , NOEKEON.ToLower()
                              , string.Empty
                          )
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case TEA:
                    Messenger.Print
                    (
                          string.Format
                          (
                                s4
                              , TEA
                              , TEA.ToLower()
                              , TEA.ToLower()
                              , string.Empty
                          )
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case XTEA:
                    Messenger.Print
                    (
                          string.Format
                          (
                                s4
                              , XTEA
                              , XTEA.ToLower()
                              , XTEA.ToLower()
                              , string.Empty
                          )
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case SEED:
                    Messenger.Print
                    (
                          string.Format
                          (
                                s4
                              , SEED
                              , SEED.ToLower()
                              , SEED.ToLower()
                              , string.Empty
                          )
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case SKIPJACK:
                    Messenger.Print
                    (
                          string.Format
                          (
                                s4
                              , SKIPJACK
                              , "sj"
                              , SKIPJACK.ToLower()
                              , string.Empty
                          )
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case GOST:
                    Messenger.Print
                    (
                         "\n\n <GOST>\n"                                                           +
                         "\n \rEncryption:\r\n\n"                                                  +
                         "\tcrypter -o file.gost -m gost -e file.bin\n"                            +
                         "\tcrypter -o file.gost -m gost -k 12345678901234567890123456789012 \\\n" +
                         "\t        -e file.bin\n\n"                                               +
                         "\tcrypter -o file.gost -m gost -s \"\" -h sha1 -e file.bin\n"            +
                         "\tcrypter -o file.gost -m gost -p \"my password\" -s \"my salt8\" \\\n"  +
                         "\t        -e file.bin\n\n"                                               +
                         "\tcrypter -o file.gost -m gost -p file:\"my password file.txt\" \\\n"    +
                         "\t        -e file.bin\n\n"                                               +
                         "\tcrypter -o file.gost -m gost --gost-box iv -e file.bin\n"              +
                         "\n \rDecryption:\r\n\n"                                                  +
                         "\tcrypter -o file.bin -m gost -d file.gost\n"                            +
                         "\tcrypter -o file.bin -m gost -k 12345678901234567890123456789012 \\\n"  +
                         "\t        -d file.gost\n\n"                                              +
                         "\tcrypter -o file.bin -m gost -s \"\" -h sha1 -d file.gost\n"            +
                         "\tcrypter -o file.bin -m gost -p \"my password\" -s \"my salt8\" \\\n"   +
                         "\t        -d file.gost\n\n"                                              +
                         "\tcrypter -o file.bin -m gost -p file:\"my password file.txt\" \\\n"     +
                         "\t        -d file.gost\n\n"                                              +
                         "\tcrypter -o file.bin -m gost --gost-box iv -d file.gost\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );

                    break;

                case RC5:
                    Messenger.Print
                    (
                         "\n\n <RC5>\n"                                                                  +
                         "\n \rEncryption:\r\n\n"                                                        +
                         "\tcrypter -o file.rc5 -m rc5 -e file.bin\n"                                    +
                         "\tcrypter -o file.rc5 -m rc5 -e -4 -5 255 -e file.bin\n"                       +
                         "\tcrypter -o file.rc5 -m rc5 -k 1234567890123456 -e file.bin\n"                +
                         "\tcrypter -o file.rc5 -m rc5 -s \"\" -h sha1 -e file.bin\n"                    +
                         "\tcrypter -o file.rc5 -m rc5 -p \"my password\" -s \"my salt8\" -e file.bin\n" +
                         "\tcrypter -o file.rc5 -m rc5 -p file:\"my password file.txt\" -e file.bin\n"   +
                         "\n \rDecryption:\r\n\n"                                                        +
                         "\tcrypter -o file.bin -m rc5 -d file.rc5\n"                                    +
                         "\tcrypter -o file.bin -m rc5 -e -4 -5 255 -d file.rc5\n"                       +
                         "\tcrypter -o file.bin -m rc5 -k 1234567890123456 -d file.rc5\n"                +
                         "\tcrypter -o file.bin -m rc5 -s \"\" -h sha1 -d file.rc5\n"                    +
                         "\tcrypter -o file.bin -m rc5 -p \"my password\" -s \"my salt8\" -d file.rc5\n" +
                         "\tcrypter -o file.bin -m rc5 -p file:\"my password file.txt\" -d file.rc5\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );

                    break;

                case RC6:
                    Messenger.Print
                    (
                         "\n\n <RC6>\n"                                                                  +
                         "\n \rEncryption:\r\n\n"                                                        +
                         "\tcrypter -o file.rc6 -m rc6 -e file.bin\n"                                    +
                         "\tcrypter -o file.rc6 -m rc6 -k 1234567890123456 -e file.bin \n"               +
                         "\tcrypter -o file.rc6 -m rc6 -s \"\" -h sha1 -e file.bin\n"                    +
                         "\tcrypter -o file.rc6 -m rc6 -p \"my password\" -s \"my salt8\" -e file.bin\n" +
                         "\tcrypter -o file.rc6 -m rc6 -p file:\"my password file.txt\" -e file.bin\n"   +
                         "\n \rDecryption:\r\n\n"                                                        +
                         "\tcrypter -o file.bin -m rc6 -d file.rc6\n"                                    +
                         "\tcrypter -o file.bin -m rc6 -k 1234567890123456 -d file.rc6\n"                +
                         "\tcrypter -o file.bin -m rc6 -s \"\" -h sha1 -d file.rc6\n"                    +
                         "\tcrypter -o file.bin -m rc6 -p \"my password\" -s \"my salt8\" -d file.rc6\n" +
                         "\tcrypter -o file.bin -m rc6 -p file:\"my password file.txt\" -d file.rc6\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case RC4:
                    Messenger.Print
                    (
                         "\n\n <RC4>\n"                                                                  +
                         "\n \rEncryption:\r\n\n"                                                        +
                         "\tcrypter -o file.rc4 -m rc4 -e file.bin\n"                                    +
                         "\tcrypter -o file.rc4 -m rc4 -y 128 -k 1234567890123456 -e file.bin \n"        +
                         "\tcrypter -o file.rc4 -m rc4 -s \"\" -h sha1 -e file.bin\n"                    +
                         "\tcrypter -o file.rc4 -m rc4 -p \"my password\" -s \"my salt8\" -e file.bin\n" +
                         "\tcrypter -o file.rc4 -m rc4 -p file:\"my password file.txt\" -e file.bin\n"   +
                         "\n \rDecryption:\r\n\n"                                                        +
                         "\tcrypter -o file.bin -m rc4 -d file.rc4\n"                                    +
                         "\tcrypter -o file.bin -m rc4 -y 128 -k 1234567890123456 -d file.rc4\n"         +
                         "\tcrypter -o file.bin -m rc4 -s \"\" -h sha1 -d file.rc4\n"                    +
                         "\tcrypter -o file.bin -m rc4 -p \"my password\" -s \"my salt8\" -d file.rc4\n" +
                         "\tcrypter -o file.bin -m rc4 -p file:\"my password file.txt\" -d file.rc4\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case HC:
                    Messenger.Print
                    (
                         "\n\n <HC>\n"                                                                 +
                         "\n \rEncryption:\r\n\n"                                                      +
                         "\tcrypter -o file.hc -m hc -e file.bin\n"                                    +
                         "\tcrypter -o file.hc -m hc -y 128 -k 1234567890123456 -e file.bin \n"        +
                         "\tcrypter -o file.hc -m hc -s \"\" -h sha1 -e file.bin\n"                    +
                         "\tcrypter -o file.hc -m hc -p \"my password\" -s \"my salt8\" -e file.bin\n" +
                         "\tcrypter -o file.hc -m hc -p file:\"my password file.txt\" -e file.bin\n"   +
                         "\n \rDecryption:\r\n\n"                                                      +
                         "\tcrypter -o file.bin -m hc -d file.hc\n"                                    +
                         "\tcrypter -o file.bin -m hc -y 128 -k 1234567890123456 -d file.hc\n"         +
                         "\tcrypter -o file.bin -m hc -s \"\" -h sha1 -d file.hc\n"                    +
                         "\tcrypter -o file.bin -m hc -p \"my password\" -s \"my salt8\" -d file.hc\n" +
                         "\tcrypter -o file.bin -m hc -p file:\"my password file.txt\" -d file.hc\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case ISAAC:
                    Messenger.Print
                    (
                         "\n\n <ISAAC>\n"                                                                  +
                         "\n \rEncryption:\r\n\n"                                                          +
                         "\tcrypter -o file.isa -m isaac -e file.bin\n"                                    +
                         "\tcrypter -o file.isa -m isaac -y 8192 -e file.bin \n"                           +
                         "\tcrypter -o file.isa -m isaac -s \"\" -h sha1 -e file.bin\n"                    +
                         "\tcrypter -o file.isa -m isaac -p \"my password\" -s \"my salt8\" -e file.bin\n" +
                         "\tcrypter -o file.isa -m isaac -p file:\"my password file.txt\" -e file.bin\n"   +
                         "\n \rDecryption:\r\n\n"                                                          +
                         "\tcrypter -o file.bin -m isaac -d file.isa\n"                                    +
                         "\tcrypter -o file.bin -m isaac -y 8192 -d file.isa\n"                            +
                         "\tcrypter -o file.bin -m hc -s \"\" -h sha1 -d file.isa\n"                       +
                         "\tcrypter -o file.bin -m hc -p \"my password\" -s \"my salt8\" -d file.isa\n"    +
                         "\tcrypter -o file.bin -m hc -p file:\"my password file.txt\" -d file.isa\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );
                    break;

                case ECIES:
                    Messenger.Print
                    (
                          "\n\n <ECIES>\n"                                                               +
                          "\n \rKey pair generation:\r\n\n"                                              +
                          "\tcrypter -m ecies -g -b public.key -v private.key\n"                         +
                          "\tcrypter -m ecies -g -b public.key -v private.key --curve-store custom \\\n" +
                          "\t        --curve curve25519\n"                                               +
                          "\n \rEncryption:\r\n\n"                                                       +
                          "\tcrypter -o file.ies -m ecies -b public.key -v private.key -e file.bin\n"    +
                          "\tcrypter -o file.ies -m ecies -b public.key -v private.key -h sha1 \\\n"     +
                          "\t        --ies-cipher rijndael -y 128 -l 128 -e file.bin\n"                  +
                          "\n \rDecryption:\r\n\n"                                                       +
                          "\tcrypter -o file.bin -m ecies -b public.key -v private.key -e file.ies\n"    +
                          "\tcrypter -o file.bin -m ecies -b public.key -v private.key -h sha1 \\\n"     +
                          "\t        --ies-cipher rijndael -y 128 -l 128 -e file.ies\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );

                    break;

                case DLIES:
                    Messenger.Print
                    (
                          "\n\n <DLIES>\n"                                                             +
                          "\n \rKey pair generation:\r\n\n"                                            +
                          "\tcrypter -m dlies -g -b public.key -v private.key\n"                       +
                          "\tcrypter -m dlies -g -b public.key -v private.key -y 1024\n"               +
                          "\n \rEncryption:\r\n\n"                                                     +
                          "\tcrypter -o file.ies -m dlies -b public.key -v private.key -e file.bin\n"  +
                          "\tcrypter -o file.ies -m dlies -b public.key -v private.key -h sha1 \\\n"   +
                          "\t        --ies-cipher rijndael -y 128 -l 128 -e file.bin\n"                +
                          "\n \rDecryption:\r\n\n"                                                     +
                          "\tcrypter -o file.bin -m dlies -b public.key -v private.key -e file.ies\n"  +
                          "\tcrypter -o file.bin -m dlies -b public.key -v private.key -h sha1 \\\n"   +
                          "\t        --ies-cipher rijndael -y 128 -l 128 -e file.ies\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );

                    break;

                case RSA:
                    Messenger.Print
                    (
                          "\n\n <RSA>\n"                                                                  +
                          "\n \rKey pair generation:\r\n\n"                                               +
                          "\tcrypter -m rsa -g -b public.key -v private.key\n"                            +
                          "\tcrypter -m rsa -g -b public.key -v private.key -y 2048 -6 128\n"             +
                          "\tcrypter -m rsa -g -f xml -b public-key.xml -v private-key.xml\n"             +
                          "\tcrypter -m rsa --rsa-bouncy-castle -g -b public.key -v private.key\n"        +
                          "\n \rEncryption:\r\n\n"                                                        +
                          "\tcrypter -o file.rsa -m rsa -b public.key -e file.bin\n"                      +
                          "\tcrypter -o file.rsa -m rsa -b public-key.xml -a -e file.bin\n"               +
                          "\tcrypter -o file.rsa -m rsa -u -b pgp-public.key -e file.bin\n"               +
                          "\tcrypter -o file.rsa -m rsa -9 file.pem -e file.bin\n"                        +
                          "\tcrypter -o file.rsa -m rsa -9 file.cer -e -a file.bin\n"                     +
                          "\tcrypter -o file.rsa -m rsa -0 \"my certificate common-name\" -e file.bin\n"  +
                          "\tcrypter -o file.rsa -m rsa --rsa-bouncy-castle -b public.key \\\n"           +
                          "\t        -e file.bin\n"                                                       +
                          "\n \rDecryption:\r\n\n"                                                        +
                          "\tcrypter -o file.rsa -m rsa -b private.key -e file.bin\n"                     +
                          "\tcrypter -o file.bin -m rsa -v private-key.xml -a -d file.rsa\n"              +
                          "\tcrypter -o file.bin -m rsa -u -v pgp-private.key -d file.rsa\n"              +
                          "\tcrypter -o file.bin -m rsa -9 file.pem -d file.rsa\n"                        +
                          "\tcrypter -o file.bin -m rsa -9 file.pfx -p \"my password\" -a -d file.rsa\n"  +
                          "\tcrypter -o file.rsa -m rsa --rsa-bouncy-castle -b private.key \\\n"          +
                          "\t        -e file.bin\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );

                    break;

                case PGP:
                    Messenger.Print
                    (
                          "\n\n <PGP>\n"                                                                 +
                          "\n \rKey pair generation:\r\n\n"                                              +
                          "\tcrypter -m pgp -g -b public.key -v private.key -y 2048 --pgp-sha1\n"        +
                          "\tcrypter -m pgp -g -f armored -b public.asc -v private.asc -q 2fish\n"       +
                          "\tcrypter -m pgp -g -b public.key -v private.key \\\n"                        +
                          "\t        --pgp-id \"My Name <my@email.com>\"\n\n"                            +
                          "\tcrypter -m pgp -pgp-algorithm elgamal -g -b public.key -v private.key\n"    +
                          "\tcrypter -m pgp -pgp-algorithm elgamal --pgp-master ecdsa \\\n"              +
                          "\t        --curve-store x962 --curve prime256v1 -g -b public.key \\\n"        +
                          "\t        -v private.key\n\n"                                                 +
                          "\n \rEncryption:\r\n\n"                                                       +
                          "\tcrypter -o file.pgp -m pgp -b public.key -q safer -e file.bin\n"            +
                          "\tcrypter -o file.pgp -m pgp -f armored -b public.asc -e file.bin\n"          +
                          "\tcrypter -o file.pgp -m pgp -u -b rsa-public.key -e file.bin\n"              +
                          "\tcrypter -o file.pgp -m pgp --pgp-algorithm elgamal -u \\\n"                 +
                          "\t        -b elgamal-public.key -e file.bin\n\n"                              +
                          "\tcrypter -o file.pgp -m pgp -9 file.pem -e file.bin\n"                       +
                          "\tcrypter -o file.pgp -m pgp -9 file.cer -e file.bin\n"                       +
                          "\tcrypter -o file.pgp -m pgp -0 \"my certificate common-name\" -e file.bin\n" +
                          "\tcrypter -o file.pgp -m pgp -0 \"my certificate common-name\" \\\n"          +
                          "\t        --pgp-sign -9 file.pfx -e file.bin\n\n"                             +
                          "\tcrypter -o file.pgp -m pgp -9 file.cer --pgp-sign -9 file.pfx \\\n"         +
                          "\t        -e file.bin\n\n"                                                    +
                          "\tcrypter -o file.pgp -m pgp -9 public.pem --pgp-sign -9 private.pem \\\n"    +
                          "\t        -e file.bin\n\n"                                                    +
                          "\tcrypter -o file.pgp -m pgp -9 file.pfx --pgp-sign -e file.bin\n"            +
                          "\tcrypter -o file.pgp -m pgp -b public.key --pgp-sign -v private.key \\\n"    +
                          "\t        -e file.bin\n\n"                                                    +
                          "\n \rDecryption:\r\n\n"                                                       +
                          "\tcrypter -o file.bin -m pgp -v private.key -d file.pgp\n"                    +
                          "\tcrypter -o file.bin -m pgp -v private.asc -d file.pgp\n"                    +
                          "\tcrypter -o file.bin -m pgp -u -v rsa-private.key -d file.pgp\n"             +
                          "\tcrypter -o file.bin -m pgp --pgp-algorithm elgamal -u \\\n"                 +
                          "\t        -b elgamal-public.key -v elgamal-private.key -d file.pgp\n\n"       +
                          "\tcrypter -o file.bin -m pgp -9 file.pem -d file.pgp\n"                       +
                          "\tcrypter -o file.bin -m pgp -9 file.pfx -p \"my password\" -d file.pgp\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );

                    break;

                case ELGAMAL:
                    Messenger.Print
                    (
                          "\n\n <ELGAMAL>\n"                                                         +
                          "\n \rKey pair generation:\r\n\n"                                          +
                          "\tcrypter -m elgamal -g -b public.key -v private.key\n"                   +
                          "\tcrypter -m elgamal -g -b public.key -v private.key -y 1024\n"           +
                          "\n \rEncryption:\r\n\n"                                                   +
                          "\tcrypter -o file.elg -m elgamal -b public.key -e file.bin\n"             +
                          "\tcrypter -o file.elg -m elgamal -b public.key -a -e file.bin\n"          +
                          "\tcrypter -o file.elg -m elgamal -b public.key -a -h sha1 -e file.bin\n"  +
                          "\n \rDecryption:\r\n\n"                                                   +
                          "\tcrypter -o file.bin -m elgamal -v private.key -d file.elg\n"            +
                          "\tcrypter -o file.bin -m elgamal -v private.key -a -d file.elg\n"         +
                          "\tcrypter -o file.bin -m elgamal -v private.key -a -h sha1 -d file.elg\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );

                    break;

                case NACCACHE:
                    Messenger.Print
                    (
                          "\n\n <NACCACHE>\n"                                               +
                          "\n \rKey pair generation:\r\n\n"                                 +
                          "\tcrypter -m naccache -g -b public.key -v private.key\n"         +
                          "\tcrypter -m naccache -g -b public.key -v private.key -y 1024\n" +
                          "\n \rEncryption:\r\n\n"                                          + 
                          "\tcrypter -o file.nac -m naccache -b public.key -e file.bin\n"   +
                          "\n \rDecryption:\r\n\n"                                          +
                          "\tcrypter -o file.bin -m naccache -v private.key -d file.nac\n"
                        , new ConsoleColor[]
                          {
                                ConsoleColor.DarkYellow
                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray

                              , ConsoleColor.Yellow
                              , ConsoleColor.Gray
                          }
                    );

                    break;

                default:
                    throw new Exception("There are no examples to the specified mode!");
            }
        }

        //----------------------------------------------------------------------------------

        private static void ShowInputNotes ()
        {
            Program.ShowBanner();
            Messenger.Print
            (
                  "\n >\r The parameter \"file:\", at the beginning of the modifier --password, allows" +
                  "\n   to obtain the complete text of a file as password.\n\r"                         +
                  "\n >\r The parameter \"batch:\", at the beginning of the input file, processes the"  +
                  "\n   input data paths as batch files. The paths must be separated by line feed"      +
                  "\n   or semicolon unless otherwise indicated.\n\r"                                   +
                  "\n >\r The semicolon character is the path delimiter unless otherwise indicated.\n"
                , new ConsoleColor[]
                  {
                      ConsoleColor.Yellow
                    , ConsoleColor.Gray
                    
                    , ConsoleColor.Yellow
                    , ConsoleColor.Gray

                    , ConsoleColor.Yellow
                    , ConsoleColor.Gray
                 }
            );
        }

        //----------------------------------------------------------------------------------

        private static string CheckArg 
        (
              string[] args
            , int      index
            , bool     strict = true
            , short    minlen = 1
            , bool     trim   = true
            , string   emsg   = null
        ){
            if (index < args.Length)
            {
                string s = trim ? args[index].Trim() : args[index];

                if (s.Length >= minlen)
                {
                    if (s.ToLower() == MOD_LONG_HELP && index - 1 > -1)
                        Program.ShowHelp(trim ? args[--index].Trim() : args[--index]);

                    else if (!strict || s.Length < 1 || s[0] != '-')
                        return s;
                }
            }

            throw new Exception(string.IsNullOrEmpty(emsg) ? MSG_MALFORMED_CMD_LINE : emsg);
        }

        //----------------------------------------------------------------------------------

        private static string CheckArg 
        (
              string[] args
            , int      index
            , bool     strict
            , short    minlen
            , string   emsg
        ){
            return Program.CheckArg(args, index, strict, minlen, true, emsg);
        }

        //----------------------------------------------------------------------------------

        private static string CheckArg (string[] args, int index, bool strict, string emsg)
        {
            return Program.CheckArg(args, index, strict, 1, emsg);
        }

        //----------------------------------------------------------------------------------

        private static string CheckArg (string[] args, int index, short minlen, string emsg)
        {
            return Program.CheckArg(args, index, true, minlen, emsg);
        }

        //----------------------------------------------------------------------------------

        private static string CheckArg (string[] args, int index, string emsg)
        {
            return Program.CheckArg(args, index, true, emsg);
        }

        //----------------------------------------------------------------------------------

        static void Main (string[] args)
        {
            int l = args.Length;

            if (l < 1)
                Program.ShowHelp();

            else
            {
                ElGamalPublicKeyParameters  epbk = null;
                ElGamalPrivateKeyParameters epvk = null;
                PgpPublicKey                ppbk = null;
                List<string>                list = new List<string>();
                int                         iaux = 0;
                short                       naux = 0;
                bool                        baux = false;
                bool                        caux = false;
                bool                        daux = false;
                string                      saux = string.Empty;
                string                      ifn  = string.Empty;
                string                      ofn  = string.Empty;
                string                      path = string.Empty;
                string                      mode = string.Empty;
                byte[]                      key  = null;
                string[]                    ifp, ofp;

                _sk.key = _sk.iv = null;

                try
                {
                    for (int i = 0; i < l; ++i)
                    {
                        switch (args[i].ToLower())
                        {
                            case "-e":
                            case "--encrypt-encode":
                                _cop = CryptOperation.ENCRYPT;
                                break;

                            case "-d":
                            case "--decrypt-decode":
                                _cop = CryptOperation.DECRYPT;
                                break;

                            case "-2":
                            case "--b32-hex":
                                _b32hex = true;
                                break;

                            case "-8":
                            case "--no-rfc4648":
                                _rfc4648 = false;
                                break;

                            case "-1":
                            case "--base-code":
                                _code    = Program.CheckArg(args, ++i, false, 2, MSG_INVALID_CODE);
                                _rfc4648 = false;
                                break;

                            case "-6":
                            case "--base-line-wrap":
                                if ((_charsperline = Convert.ToInt16(Program.CheckArg(args, ++i))) < 0)
                                    throw new Exception("The base line wrap can not be less than 0!");

                                break;

                            case "-x":
                            case "--max-buffer-size":
                                if ((_buffersize = Convert.ToInt32(Program.CheckArg(args, ++i, MSG_INVALID_BUFFER_SIZE))) < 1)
                                    throw new Exception("The buffer size can not be less than 1!");

                                break;

                            case "-o":
                            case "--output":
                                ofn = Program.CheckArg(args, ++i, false, 0);
                                break;

                            case MOD_SHORT_KEY_SIZE:
                            case MOD_LONG_KEY_SIZE:
                                _keysize = Convert.ToInt16(Program.CheckArg(args, ++i, MSG_INVALID_KEY_SIZE));

                                if (_keysize < 0)
                                    throw new Exception(MSG_INVALID_KEY_SIZE);

                                break;

                            case "-l":
                            case "--block-size":
                                _blocksize = Convert.ToInt16(Program.CheckArg(args, ++i, MSG_INVALID_BLOCK_SIZE));

                                if (_blocksize < 0)
                                    throw new Exception(MSG_INVALID_BLOCK_SIZE);

                                break;

                            case "-z":
                            case "--feedback-size":
                                _feedbacksize = Convert.ToInt16(Program.CheckArg(args, ++i, MSG_INVALID_FEEDBACK_SIZE));

                                if (_feedbacksize < 0)
                                    throw new Exception(MSG_INVALID_FEEDBACK_SIZE);

                                break;

                            case MOD_SHORT_MODE:
                            case MOD_LONG_MODE:
                                mode = Program.CheckArg(args, ++i).ToUpper();
                                break;

                            case "-p":
                            case "--password":
                                if (string.IsNullOrEmpty(_password) || !_export)
                                {
                                    _password = Program.CheckArg(args, ++i, false, 0, false);

                                    if (_password.IndexOf("file:", StringComparison.InvariantCultureIgnoreCase) == 0)
                                        _password = File.ReadAllText(_password.Substring(5));
                                }

                                else _export_pwd = Program.CheckArg(args, ++i, false, 0, false);
                                break;

                            case "-s":
                            case "--salt":
                                _salt        = Program.CheckArg(args, ++i, false, 0, false);
                                _saltleaking = true;
                                break;

                            case "-k":
                            case "--key":
                                _key = Program.CheckArg(args, ++i, false, 0, false);
                                break;

                            case "-i":
                            case "--initial-vector":
                                _iv = Program.CheckArg(args, ++i, false, 0, false);
                                break;

                            case "-t":  
                            case "--iterations":
                                if ((_iterations = Convert.ToInt32(Program.CheckArg(args, ++i))) < 1)
                                    throw new Exception("The iterations can not be less than 1!");

                                break;

                            case "-c":
                            case "--cipher-mode":
                                switch (Program.CheckArg(args, ++i).ToUpper())
                                {
                                    case "CBC":
                                        _ciphermode = CipherMode.CBC;
                                        break;
                                        
                                    case "CTS":
                                        _ciphermode = CipherMode.CTS;
                                        break;                                        

                                    case "ECB":
                                        _ciphermode = CipherMode.ECB;
                                        break;

                                    case "CFB":
                                        _ciphermode = CipherMode.CFB;
                                        break;

                                    case "OFB":
                                        _ciphermode = CipherMode.OFB;
                                        break;

                                    default:
                                        throw new Exception(MSG_INVALID_CIPHER_MODE);
                                }
                                break;

                            case "-n":
                            case "--padding":
                                daux = true;
                                switch (Program.CheckArg(args, ++i).ToUpper())
                                {
                                    case "ANSIX923":
                                        _padding = CryptPadding.ANSIX923;
                                        break;

                                    case "ISO10126":
                                        _padding = CryptPadding.ISO10126;
                                        break;

                                    case "ISO7816":
                                        _padding = CryptPadding.ISO7816;
                                        break;

                                    case "PKCS7":
                                        _padding = CryptPadding.PKCS7;
                                        break;

                                    case "PKCS1":
                                        _padding = CryptPadding.PKCS1;
                                        break;

                                    case "ZEROS":
                                        _padding = CryptPadding.Zeros;
                                        break;

                                    case "TBC":
                                        _padding = CryptPadding.TBC;
                                        break;

                                    case "ISO9796D1":
                                        _padding = CryptPadding.ISO9796D1;
                                        break;

                                    default:
                                        throw new Exception(MSG_INVALID_PADDING_MODE);
                                }
                                break;

                            case "--asymmetric-padding":
                                break;

                            case MOD_SHORT_HASH:
                            case MOD_LONG_HASH:
                                _hash = Program.CheckArg(args, ++i).ToUpper();
                                break;

                            case "-r":
                            case "--random-gen":
                                _random = true;
                                break;

                            case "-g":
                            case "--key-pair-gen":
                                _generator = true;
                                break;

                            case "-b":
                            case "--public-key":
                                if (string.IsNullOrEmpty(_public_key) || !_export)
                                     _public_key = Program.CheckArg(args, ++i, false, MSG_INVALID_PUBLIC_KEY);

                                else _export_pbk = Program.CheckArg(args, ++i, false, MSG_INVALID_PUBLIC_KEY); 
                                break;

                            case "-v":
                            case "--private-key":
                                if (string.IsNullOrEmpty(_private_key) || !_export)
                                     _private_key = Program.CheckArg(args, ++i, false, MSG_INVALID_PRIVATE_KEY);

                                else _export_pvk  = Program.CheckArg(args, ++i, false, MSG_INVALID_PRIVATE_KEY);
                                break;

                            case "-a":
                            case "--oaep":
                                _padding = CryptPadding.OAEP;
                                daux     = true;
                                break;

                            case "-9": 
                            case "--x509-file":
                                if (string.IsNullOrEmpty(_cerfile) || !_pgp_sign)
                                    _cerfile = Program.CheckArg(args, ++i, false);

                                else _cer_pgp_pvk = Program.CheckArg(args, ++i, false);
                                break;

                            case "-0":
                            case "--x509-name":
                                _cerstore = Program.CheckArg(args, ++i, false);
                                break;

                            case "-f":
                            case "--format":
                                switch (Program.CheckArg(args, ++i).ToUpper())
                                {
                                    case "XML":
                                        _format = CryptFormat.XML;
                                        break;
                                        
                                    case "BLOB":
                                        _format = CryptFormat.BLOB;
                                        break;

                                    case "ARMORED":
                                        _format = CryptFormat.ARMORED;
                                        break;

                                    default:
                                        throw new Exception("Invalid format!");
                                }

                                break;
                            
                            case "q":
                            case "--pgp-cipher":
                                switch (Program.CheckArg(args, ++i).ToUpper())
                                {
                                    case "AES128":
                                        _ska = SymmetricKeyAlgorithmTag.Aes128;
                                        break;

                                    case "AES192":
                                        _ska = SymmetricKeyAlgorithmTag.Aes192;
                                        break;

                                    case "AES256":
                                        _ska = SymmetricKeyAlgorithmTag.Aes256;
                                        break;

                                    case BLOWFISH:
                                        _ska = SymmetricKeyAlgorithmTag.Blowfish;
                                        break;

                                    case CAST5:
                                        _ska = SymmetricKeyAlgorithmTag.Cast5;
                                        break;

                                    case DES:
                                        _ska = SymmetricKeyAlgorithmTag.Des;
                                        break;

                                    case IDEA:
                                        _ska = SymmetricKeyAlgorithmTag.Idea;
                                        break;

                                    case "SAFER":
                                        _ska = SymmetricKeyAlgorithmTag.Safer;
                                        break;

                                    case TDES:
                                        _ska = SymmetricKeyAlgorithmTag.TripleDes;
                                        break;

                                    case TWOFISH:
                                        _ska = SymmetricKeyAlgorithmTag.Twofish;
                                        break; 

                                    case "CAMELLIA128":
                                        _ska = SymmetricKeyAlgorithmTag.Camellia128;
                                        break;

                                    case "CAMELLIA192":
                                        _ska = SymmetricKeyAlgorithmTag.Camellia192;
                                        break;

                                    case "CAMELLIA256":
                                        _ska = SymmetricKeyAlgorithmTag.Camellia256;
                                        break;

                                    default:
                                        throw new Exception("Invalid Pgp symmetric cipher!");
                                }
                                break;

                            case "-u":
                            case "--crossbreeding":
                                _crossbreeding = true;
                                break;

                            case "-5":
                            case "--rounds":
                                _rounds = Convert.ToInt32(Program.CheckArg(args, ++i));
                                break;

                            case "-4":
                            case "--rc5-64b":
                                _rc5b64 = true;
                                break;

                            case "-3":
                            case "--vmpc-ksa3":
                                _ksa3 = true;
                                break;

                            case "-j":
                            case "--tell-apart":
                                _tellapart = true;
                                break;

                            case "-w":
                            case "--overwrite":
                                _overwrite = true;
                                break;

                            case MOD_SHORT_IO_OPTIONS:
                            case MOD_LONG_IO_OPTIONS:
                                
                                ifp = Program.CheckArg(args, ++i).Split
                                (
                                      _io_options_separator
                                    , StringSplitOptions.RemoveEmptyEntries
                                );

                                foreach (string s in ifp) switch (s.Trim().ToLower())
                                { 
                                    case "basic":
                                        _findermode = Finder.Mode.Basic;
                                        break;

                                    case "glob":
                                        _findermode = Finder.Mode.Glob;
                                        break;

                                    case "extglob":
                                        _findermode = Finder.Mode.ExtendedGlob;
                                        break;

                                    case "regex":
                                        _findermode = Finder.Mode.Regex;
                                        break;

                                    case "unignore-case":
                                        _ignorecase = false;
                                        break;

                                    case "recursively":
                                        _recursively = true;
                                        break;

                                    case "reverse":
                                        _reverse = true;
                                        break;

                                    default:
                                        throw new Exception("Invalid input-output option: \"" + s + '"');
                                }

                                Array.Clear(ifp, 0, ifp.Length);
                                break;

                            case MOD_LONG_EXPORT:
                                if (i + 1 <= l - 1)
                                    Program.CheckArg(args, i + 1, false);

                                _export = true;
                                break;

                            case "--encoding":
                                switch (Program.CheckArg(args, ++i).ToUpper())
                                {
                                    case "ASCII":
                                        _encoding = Encoding.ASCII;
                                        break;

                                    case "UNICODE":
                                    case "UNICODE-LE":
                                        _encoding = Encoding.Unicode;
                                        break;

                                    case "UNICODE-BE":
                                        _encoding = Encoding.BigEndianUnicode;
                                        break;

                                    case "UTF-7":
                                        _encoding = Encoding.UTF7;
                                        break;

                                    case "UTF-8":
                                        _encoding = Encoding.UTF8;
                                        break;

                                    case "UTF-32":
                                        _encoding = Encoding.UTF32;
                                        break;

                                    default:
                                        throw new Exception("Invalid encoding mode!");
                                }
                                break;

                            case "--without-iv-tweak":
                                _without_iv = true;
                                break;

                            case "--rsa-bouncy-castle":
                                _rsa_bc = true;
                                break;

                            case "--gost-box":
                                _sbox = Program.CheckArg(args, ++i, true, 0).ToUpper();
                                break;

                            case "--pgp-algorithm":
                                _pgp_algorithm = Program.CheckArg(args, ++i).ToUpper();
                                break;

                            case "--pgp-id":
                                _pgp_id = Program.CheckArg(args, ++i).ToUpper();
                                break;

                            case "--pgp-sha1":
                                _sha1 = true;
                                break;

                            case "--pgp-master":
                                _pgp_master = Program.CheckArg(args, ++i).ToUpper();
                                break;

                            case "--pgp-sign":
                                _pgp_sign = true;
                                break;

                            case "--ies-cipher":
                                _ies_cipher = Program.CheckArg(args, ++i, true, 0).ToUpper();
                                break;

                            case "--curve":
                                _curve = Program.CheckArg(args, ++i).ToLower();
                                break;

                            case "--curve-store":
                                _curvestore = Program.CheckArg(args, ++i).ToUpper();
                                break;

                            case "--show-store-curves":
                                if (++i <= l - 1)
                                    _curvestore = Program.CheckArg(args, i).ToUpper();

                                caux = true;
                                break;

                            case "--raise-pwd-exception":
                                _raisepwd = true;
                                break;

                            case "--inhibit-errors":
                                _raise = false;
                                break;

                            case "--inhibit-esc-chars":
                                _unesc = true;
                                break;

                            case "--inhibit-delimiter":
                                _pathdelimiter = false;
                                break;

                            case MOD_LONG_HELP:
                                if (++i <= l - 1)
                                    Program.ShowHelp(Program.CheckArg(args, i, false));

                                else
                                {
                                    Program.ShowHelp();
                                    Environment.Exit(0);
                                }

                                break;

                            case "--examples":
                                if (++i <= l - 1)
                                {
                                    Program.ShowExamples(Program.CheckArg(args, i));
                                    Environment.Exit(0);
                                }

                                else baux = true;
                                break;

                            case "--input-notes":
                                Program.ShowInputNotes();
                                Environment.Exit(0);
                                break;

                            default:
                                ifn = Program.CheckArg(args, i, false);
                                break;
                        }
                    }

                    if (_cop == CryptOperation.NONE && !string.IsNullOrEmpty(ifn))
                        throw new Exception(MSG_MALFORMED_CMD_LINE);

                    if (baux)
                    {
                        if (!string.IsNullOrEmpty(mode))
                            Program.ShowExamples(mode);

                        else
                        {
                            string[] modes =
                            { 
                                  B2, B3, B4, B5, B6, B7, B8, B9, B10, B11, B12, B13, B14, B15
                                , B16, B17, B18, B19, B20, B21, B22, B23, B24, B25, B26, B27
                                , B28, B29, B30, B31, B32, B33, B34, B35, B36, B37, B38, B39
                                , B40, B41, B42, B43, B44, B45, B46, B47, B48, B49, B50, B51
                                , B52, B53, B54, B55, B56, B57, B58, B59, B60, B61, B62, B63
                                , B64, DIGEST, CHECKSUM, AES, RIJNDAEL, TDES, DES, MARS
                                , SALSA20, XSALSA20, CHACHA, VMPC, RC2, CAMELLIA, BLOWFISH
                                , TWOFISH, THREEFISH, SERPENT, CAST5, CAST6, IDEA, NOEKEON
                                , TEA, XTEA, GOST, SEED, SKIPJACK, RC4, RC5, RC6, HC, ISAAC
                                , ECIES, DLIES, RSA, PGP, ELGAMAL, NACCACHE
                            };

                            foreach (string s in modes)
                                Program.ShowExamples(s);
                        }

                        Environment.Exit(0);
                    }

                    if (caux)
                    {
                        Program.DisplayCurveNames();
                        Environment.Exit(0);
                    }

                    if (_export && _generator)
                        throw new Exception(MSG_EXPORT_USE);

                    if (_random && _cop != CryptOperation.ENCRYPT)
                    {
                        _random = false;
                        Messenger.Print
                        (
                              Messenger.Icon.WARNING
                            , string.Format(MSG_GENERIC_USE, RANDOM)
                            , false
                            , true
                        );
                    }

                    Program.ShowBanner();

                    if (_cop == CryptOperation.NONE)
                    {
                        if (mode == DIGEST || mode == CHECKSUM)
                        {
                            Program.ValidateParams(0x1111111111111111, 0x1111111111111111);

                            if (!File.Exists(ifn))
                                throw new Exception("Invalid input file name!");

                            Messenger.Print(Messenger.Icon.INFORMATION, MSG_PROCESSING);

                            using (FileStream fsr = File.OpenRead(ifn))
                            {
                                _key = mode == DIGEST ? Program.Digest(fsr) : Program.Checksum(fsr);

                                if (string.IsNullOrEmpty(ofn))
                                {
                                    if (_key.Length > Messenger.MaxWidth - 5)
                                        _key += '\n';

                                    Messenger.Print(Messenger.Icon.INFORMATION, _key);
                                    Messenger.Print(Messenger.Icon.INFORMATION, MSG_DONE);
                                }

                                else
                                {
                                    if (!Program.ValidatePath(ofn) || Path.GetFullPath(ifn) == Path.GetFullPath(ofn))
                                        throw new Exception(MSG_INVALID_OUTPUT);

                                    if (Program.OverwriteFileCheck(ofn, _overwrite))
                                    {
                                        key = Encoding.ASCII.GetBytes(_key);

                                        using (FileStream fsw = File.Create(ofn))
                                            fsw.Write(key, 0, key.Length);

                                        Array.Clear(key, 0, key.Length);
                                        Messenger.Print(Messenger.Icon.INFORMATION, MSG_DONE);
                                    }
                                }
                            }

                            Environment.Exit(0);
                        }

                        else if (_generator && mode == RSA)
                        {
                            Program.ValidateParams(0x1111111111110111, 0x0111111110100111);

                            if (!string.IsNullOrEmpty(ofn)) Messenger.Print
                            (
                                  Messenger.Icon.WARNING
                                , string.Format(MSG_GENERIC_USE, OUT)
                                , false
                                , true
                            );

                            Program.RsaValidateKeySize();
                            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(_keysize))
                                Program.RsaKeyPairGen(rsa);

                            Messenger.Print(Messenger.Icon.INFORMATION, MSG_DONE);
                            Environment.Exit(0);
                        }

                        else if (_export && mode == RSA)
                        {
                            Program.ValidateParams(0x1111101111110111, 0x1111111110000111);

                            if (!string.IsNullOrEmpty(ofn)) Messenger.Print
                            (
                                  Messenger.Icon.WARNING
                                , string.Format(MSG_GENERIC_USE, OUT)
                                , false
                                , true
                            );

                            if (!string.IsNullOrEmpty(_cerfile))
                                using (RSACryptoServiceProvider rsa = Program.GetRsaFromCertificateFile(CryptOperation.DECRYPT))
                                    Program.RsaKeyPairGen(rsa);

                            else if (!string.IsNullOrEmpty(_cerstore))
                                using (RSACryptoServiceProvider rsa = Program.GetRsaFromCertificateStore())
                                    Program.RsaKeyPairGen(rsa);

                            else if (!string.IsNullOrEmpty(_export_pvk))
                            { 
                                if (!File.Exists(_private_key))
                                    throw new Exception(MSG_INVALID_PRIVATE_KEY);

                                using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                                {
                                    baux    = _format == CryptFormat.ARMORED;
                                    _format = CryptFormat.UNKNOWN;

                                    Program.RsaImportKey(rsa, _private_key);

                                    if (!string.IsNullOrEmpty(_export_pvk))
                                        _private_key = _export_pvk;

                                    if (!string.IsNullOrEmpty(_export_pbk))
                                        _public_key  = _export_pbk;

                                    Program.PgpRsaKeyPairGen(baux, rsa);
                                }

                            }

                            else if (!string.IsNullOrEmpty(_export_pbk))
                            {
                                if (!File.Exists(_public_key))
                                    throw new Exception(MSG_INVALID_PUBLIC_KEY);

                                using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                                {
                                    baux    = _format == CryptFormat.ARMORED;
                                    _format = CryptFormat.UNKNOWN;

                                    Program.RsaImportKey(rsa, _public_key);

                                    if (!string.IsNullOrEmpty(_export_pvk))
                                        _private_key = _export_pvk;

                                    if (!string.IsNullOrEmpty(_export_pbk))
                                        _public_key = _export_pbk;

                                    Program.PgpRsaKeyPairGen(baux, rsa);
                                }
                            }

                            else throw new Exception(MSG_INVALID_EXPORT_PARAMS);

                            Messenger.Print(Messenger.Icon.INFORMATION, MSG_DONE);
                            Environment.Exit(0);
                        }

                        else if (_generator && mode == PGP)
                        {  
                            Program.ValidateParams(0x1111111111111111, 0x0111110110100111);

                            if (!string.IsNullOrEmpty(ofn)) Messenger.Print
                            (
                                  Messenger.Icon.WARNING
                                , string.Format(MSG_GENERIC_USE, OUT)
                                , false
                                , true
                            );

                            if (_pgp_sign) 
                                Messenger.Print(Messenger.Icon.WARNING, MSG_PGP_SIGN_USE, false, true);

                            if (_pgp_algorithm == RSA) 
                                Program.PgpRsaKeyPairGen(_format == CryptFormat.ARMORED);

                            else if (_pgp_algorithm == ELGAMAL)
                            {
                                if (_keysize == -1)
                                    _keysize = 768;

                                Program.PgpElGamalKeyPairGen(_format == CryptFormat.ARMORED);
                            }

                            else throw new Exception(MSG_INVALID_PGP_ALGORITHM);

                            Messenger.Print(Messenger.Icon.INFORMATION, MSG_DONE);
                            Environment.Exit(0);
                        }

                        else if (_export && mode == PGP)
                        {
                            Program.ValidateParams(0x1111101111111111, 0x1111110110000111);

                            if (!string.IsNullOrEmpty(ofn)) Messenger.Print
                            (
                                  Messenger.Icon.WARNING
                                , string.Format(MSG_GENERIC_USE, OUT)
                                , false
                                , true
                            );

                            if (_pgp_sign) 
                                Messenger.Print(Messenger.Icon.WARNING, MSG_PGP_SIGN_USE, false, true);

                            if (!string.IsNullOrEmpty(_cerfile))
                            {
                                if (_pgp_algorithm != RSA) Messenger.Print
                                (
                                      Messenger.Icon.WARNING
                                    , MSG_CER_ALG_INCOMPATIBLE
                                    , false
                                    , true
                                );

                                using (RSACryptoServiceProvider rsa = Program.GetRsaFromCertificateFile(CryptOperation.DECRYPT))
                                {
                                    if (!string.IsNullOrEmpty(_export_pwd))
                                        _password = _export_pwd;

                                    else if (!string.IsNullOrEmpty(_password) && !Program.Question(MSG_EXPORT_PWD_QUESTION))
                                        _password = string.Empty;

                                    Program.PgpRsaKeyPairGen(_format == CryptFormat.ARMORED, rsa);
                                }
                            }

                            else if (!string.IsNullOrEmpty(_cerstore))
                            {
                                if (_pgp_algorithm != RSA) Messenger.Print
                                (
                                      Messenger.Icon.WARNING
                                    , MSG_CER_ALG_INCOMPATIBLE
                                    , false
                                    , true
                                );

                                using (RSACryptoServiceProvider rsa = Program.GetRsaFromCertificateStore())
                                    Program.PgpRsaKeyPairGen(_format == CryptFormat.ARMORED, rsa);
                            }

                            else
                            {
                                if (!string.IsNullOrEmpty(_private_key))
                                {
                                    if (string.IsNullOrEmpty(_export_pvk) || !File.Exists(_private_key))
                                        throw new Exception(MSG_INVALID_PRIVATE_KEY);

                                    _pgp_pvk = Program.GetPgpPrivateKey();
                                }

                                if (!string.IsNullOrEmpty(_public_key))
                                {
                                    if (string.IsNullOrEmpty(_export_pbk))
                                        _export_pbk = _public_key;

                                    else
                                    {
                                        if (!File.Exists(_public_key))
                                            throw new Exception(MSG_INVALID_PUBLIC_KEY);

                                        ppbk = Program.GetPgpPublicKey();
                                    }
                                }

                                if (_pgp_pvk != null || ppbk != null)
                                {
                                    _private_key = _export_pvk;
                                    _public_key  = _export_pbk;

                                    if (_pgp_pvk != null)
                                        Program.AssertPgpAlgorithm(_pgp_pvk.PublicKeyPacket.Algorithm);

                                    else if (ppbk != null)
                                        Program.AssertPgpAlgorithm(ppbk.Algorithm);

                                    switch (_pgp_algorithm)
                                    {
                                        case RSA:
                                            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                                            {
                                                if (_pgp_pvk != null)
                                                    Program.PgpPrivateKeyToRsa(_pgp_pvk, rsa);

                                                else if (ppbk != null)
                                                    Program.PgpPublicKeyToRsa(ppbk, rsa);

                                                Program.RsaKeyPairGen(rsa);
                                            }

                                            break;

                                        case ELGAMAL:
                                            Program.ElGamalKeyPairGen
                                            (
                                                  true
                                                , Program.PgpPublicKeyToElGamal(ppbk)
                                                , Program.PgpPrivateKeyToElGamal(_pgp_pvk)
                                            );

                                            break;
                                    }
                                }

                                else throw new Exception(MSG_INVALID_EXPORT_PARAMS);
                            }

                            Messenger.Print(Messenger.Icon.INFORMATION, MSG_DONE);
                            Environment.Exit(0);
                        }

                        else if (_generator && mode == ELGAMAL)
                        {
                            Program.ValidateParams(0x1111111111111111, 0x1111111111100111);

                            if (!string.IsNullOrEmpty(ofn)) Messenger.Print
                            (
                                  Messenger.Icon.WARNING
                                , string.Format(MSG_GENERIC_USE, OUT)
                                , false
                                , true
                            );

                            if (_keysize == -1)
                                _keysize = 768;

                            Program.ElGamalKeyPairGen();
                            Messenger.Print(Messenger.Icon.INFORMATION, MSG_DONE);
                            Environment.Exit(0);
                        }

                        else if (_export && mode == ELGAMAL)
                        {
                            Program.ValidateParams(0x1111111111111111, 0x1111111111100111);

                            if (!string.IsNullOrEmpty(ofn)) Messenger.Print
                            (
                                  Messenger.Icon.WARNING
                                , string.Format(MSG_GENERIC_USE, OUT)
                                , false
                                , true
                            );

                            if (_pgp_sign)
                                Messenger.Print(Messenger.Icon.WARNING, MSG_PGP_SIGN_USE, false, true);

                            if (string.IsNullOrEmpty(_private_key) || !File.Exists(_private_key))
                                throw new Exception(MSG_INVALID_PRIVATE_KEY);

                            if (string.IsNullOrEmpty(_public_key) || !File.Exists(_public_key))
                                throw new Exception(MSG_INVALID_PUBLIC_KEY);

                            epvk         = (ElGamalPrivateKeyParameters)Program.ElGamalImportKey(_private_key);
                            epbk         = (ElGamalPublicKeyParameters)Program.ElGamalImportKey(_public_key);
                            _private_key = _export_pvk;
                            _public_key  = _export_pbk;

                            Program.PgpElGamalKeyPairGen
                            (
                                  _format == CryptFormat.ARMORED
                                , new AsymmetricCipherKeyPair(epbk, epvk)
                            );

                            Messenger.Print(Messenger.Icon.INFORMATION, MSG_DONE);
                            Environment.Exit(0);
                        }

                        else if (_generator && mode == NACCACHE)
                        {
                            Program.ValidateParams(0x1111111111111111, 0x1111111111100111);

                            if (!string.IsNullOrEmpty(ofn)) Messenger.Print
                            (
                                  Messenger.Icon.WARNING
                                , string.Format(MSG_GENERIC_USE, OUT)
                                , false
                                , true
                            );

                            if (_keysize == -1)
                                _keysize = 768;

                            Program.NaccacheSternKeyPairGen();
                            Messenger.Print(Messenger.Icon.INFORMATION, MSG_DONE);
                            Environment.Exit(0);
                        }

                        else if (_generator && mode == ECIES)
                        {
                            Program.ValidateParams(0x1111111111111111, 0x1101111111100111);

                            if (!string.IsNullOrEmpty(ofn)) Messenger.Print
                            (
                                  Messenger.Icon.WARNING
                                , string.Format(MSG_GENERIC_USE, OUT)
                                , false
                                , true
                            );

                            Program.EciesKeyPairGen();
                            Messenger.Print(Messenger.Icon.INFORMATION, MSG_DONE);
                            Environment.Exit(0);
                        }

                        else if (_generator && mode == DLIES)
                        {
                            Program.ValidateParams(0x1111111111111111, 0x1111111111100111);

                            if (!string.IsNullOrEmpty(ofn)) Messenger.Print
                            (
                                  Messenger.Icon.WARNING
                                , string.Format(MSG_GENERIC_USE, OUT)
                                , false
                                , true
                            );

                            if (_keysize == -1)
                                _keysize = 768;

                            Program.DliesKeyPairGen();
                            Messenger.Print(Messenger.Icon.INFORMATION, MSG_DONE);
                            Environment.Exit(0);
                        }

                        else throw new Exception("Invalid encrypt-encode or decrypt-decode operation indicator!");
                    }

                    if (_generator && _cop == CryptOperation.DECRYPT)
                    {
                        Messenger.Print(Messenger.Icon.WARNING, MSG_GEN_INCOMPATIBLE, false, true);
                        _generator = false;
                    }

                    if (_export)
                    {
                        Messenger.Print(Messenger.Icon.WARNING, MSG_EXPORT_USE, false, true);
                        _export = false;
                    }

                    if (ofn.EndsWith(Path.DirectorySeparatorChar.ToString()))
                        ofn = ofn.Remove(ofn.Length - 1);

                    if (baux = ifn.IndexOf("batch:", StringComparison.InvariantCultureIgnoreCase) == 0)
                        ifn = ifn.Substring(5);

                    ofp = !_pathdelimiter ? new string[] { ifn } : ifn.Split
                    (
                          _path_delimiter
                        , StringSplitOptions.RemoveEmptyEntries
                    );

                    _finder = new Finder(_findermode);
                    _finder.RaiseAccessDenied = false;

                    foreach (string s in ofp) list.AddRange
                    (
                        _finder.GetFiles
                        (
                              s
                            , _ignorecase
                            , _reverse
                            , _recursively
                        )
                    );

                    Array.Clear(ofp, 0, ofp.Length);
                    ifp = list.ToArray();
                    list.Clear();

                    if (baux)
                    {
                        foreach (string s in ifp)
                        {
                            using (FileStream fsr = File.OpenRead(s))
                            {
                                using (StreamReader sr = new StreamReader(fsr))
                                {
                                    while (sr.Peek() >= 0)
                                    {
                                        if (!_pathdelimiter)
                                             ofp = new string[] { sr.ReadLine() };

                                        else ofp = sr.ReadLine().Split
                                        (
                                              _path_delimiter
                                            , StringSplitOptions.RemoveEmptyEntries
                                        );
                                        
                                        l = ofp.Length;
                                        for (int i = 0; i < l; ++i) list.AddRange
                                        (
                                            _finder.GetFiles
                                            (
                                                  ofp[i]
                                                , _ignorecase
                                                , _reverse
                                                , _recursively
                                            )
                                        );

                                        Array.Clear(ofp, 0, l);
                                    }
                                }
                            }
                        }

                        Array.Clear(ifp, 0, ifp.Length);
                        ifp = list.ToArray();
                        list.Clear();
                    }

                    if ((l = ifp.Length) < 1) 
                        throw new Exception(String.Format(MSG_FILE_WAS_NOT_FOUND, ifn));

                    else if (l == 1)
                    {
                        _tellapart = false;
                        _raise     = true;

                        if (string.IsNullOrEmpty(ofn))
                            ofn = ifp[0];

                        else
                        {   
                            ofp = _finder.GetDirectories(ofn, _ignorecase);

                            if (ofp.Length == 1)
                                ofn = ofp[0] + Path.DirectorySeparatorChar + Path.GetFileName(ifp[0]);

                            else if (ofp.Length > 1)
                                throw new Exception(MSG_INVALID_OUTPUT);

                            else
                            {
                                Array.Clear(ofp, 0, ofp.Length);

                                ofp = _finder.GetFiles(ofn, _ignorecase);

                                if (ofp.Length == 1)
                                    ofn = ofp[0];

                                else if (ofp.Length > 1)
                                    throw new Exception(MSG_INVALID_OUTPUT);
                            }

                            Array.Clear(ofp, 0, ofp.Length);
                        }

                        if (!Program.ValidatePath(ofn))
                            throw new Exception(MSG_INVALID_OUTPUT);

                        Program.OverwriteFileCheck(ofn = Path.GetFullPath(ofn), _overwrite);
                    }

                    else if (l > 1)
                    {
                        if (string.IsNullOrEmpty(ofn))
                            iaux = l;

                        else
                        {
                            ofp  = _finder.GetDirectories(ofn, _ignorecase);
                            ofn  = string.Empty;
                            iaux = 0;

                            if (ofp.Length == 1)
                            {
                                path = Path.GetFullPath(ofp[0]) + Path.DirectorySeparatorChar;

                                foreach (string s in ifp)
                                    if (File.Exists(path + Path.GetFileName(s)))
                                        ++iaux;

                                if (iaux < 1)
                                    _overwrite = true;
                            }

                            else if (ofp.Length > 1)
                                throw new Exception(MSG_INVALID_OUTPUT);

                            else
                            {
                                ofn  = "The specified output file will not be considered.";
                                iaux = l;
                            }

                            Array.Clear(ofp, 0, ofp.Length);
                        }

                        if (!_overwrite) Program.Question
                        (
                              l + " files were found, of which " + iaux + " will be overwritten. " + ofn + 
                              MSG_CONTINUE_QUESTION
                            , true
                        );
                    }

                    Messenger.Print(Messenger.Icon.INFORMATION, MSG_PROCESSING);

                    naux = _blocksize;
                    baux = caux = false;

	                for (int i = 0; i < l; ++i)
	                {
                        try
					    {
	                        ifn        = Path.GetFullPath(ifp[i]);
                            _overwrite = false;
	
	                        if (!string.IsNullOrEmpty(path))
	                            ofn = path + Path.GetFileName(ifn);

                            else if ((_overwrite = l > 1))
	                            ofn = Path.GetTempFileName();
	
	                        if (ifn == ofn)
	                        {
	                            ofn        = Path.GetTempFileName();
                                _overwrite = true;
	                        }

		                    using (FileStream fsr = File.OpenRead(ifn))
		                    {
		                        using (FileStream fsw = File.Create(ofn))
		                        {
		                            switch (mode)
		                            {
	                                    case BIN:
	                                        mode = B2;
	                                        goto case B63;
	
	                                    case HEX:
	                                        mode = B16;
	                                        goto case B63;
	
	                                    case OCTAL:
	                                        mode = B8;
	                                        goto case B63;
	
	                                    case DECIMAL:
	                                        mode = B10;
	                                        goto case B63;
	
	                                    case B2:
	                                    case B3:
	                                    case B4:
	                                    case B5:
	                                    case B6:
	                                    case B7:
	                                    case B8:
	                                    case B9:
	                                    case B10:
	                                    case B11:
	                                    case B12:
	                                    case B13:
	                                    case B14:
	                                    case B15:
	                                    case B16:
	                                    case B17:
	                                    case B18:
	                                    case B19:
	                                    case B20:
	                                    case B21:
	                                    case B22:
	                                    case B23:
	                                    case B24:
	                                    case B25:
	                                    case B26:
	                                    case B27:
	                                    case B28:
	                                    case B29:
	                                    case B30:
	                                    case B31:
	                                    case B33:
	                                    case B34:
	                                    case B35:
	                                    case B36:
	                                    case B37:
	                                    case B38:
	                                    case B39:
	                                    case B40:
	                                    case B41:
	                                    case B42:
	                                    case B43:
	                                    case B44:
	                                    case B45:
	                                    case B46:
	                                    case B47:
	                                    case B48:
	                                    case B49:
	                                    case B50:
	                                    case B51:
	                                    case B52:
	                                    case B53:
	                                    case B54:
	                                    case B55:
	                                    case B56:
	                                    case B57:
	                                    case B58:
	                                    case B59:
	                                    case B60:
	                                    case B61:
	                                    case B62:
	                                    case B63:
                                            Program.ValidateParams(0x1111111111110010, 0x1111111111111111);

                                            if (!baux)
                                                Program.ValidateParams(1, 0);

	                                        if (_cop == CryptOperation.ENCRYPT)
	                                            Program.Encode(fsr, fsw, byte.Parse(mode.Substring(1)));
	
	                                        else if (_cop == CryptOperation.DECRYPT)
	                                            Program.Decode(fsr, fsw, byte.Parse(mode.Substring(1)));
	
	                                        break;
	
	                                    case B32:
                                            baux = true;

	                                        if (!_rfc4648)
	                                            goto case B63;

                                            Program.ValidateParams(0x1111111111110100, 0x1111111111111111);
	
	                                        if (_cop == CryptOperation.ENCRYPT)
	                                            Program.Base32Encode(fsr, fsw);
	
	                                        else if (_cop == CryptOperation.DECRYPT)
	                                            Program.Base32Decode(fsr, fsw);
	
	                                        break;
	
	                                    case B64:
                                            baux = true;

	                                        if (!_rfc4648)
	                                            goto case B63;

                                            Program.ValidateParams(0x1111111111110110, 0x1111111111111111);
	
	                                        if (_cop == CryptOperation.ENCRYPT)
	                                            Program.Base64Encode(fsr, fsw);
	
	                                        else if (_cop == CryptOperation.DECRYPT)
	                                            Program.Base64Decode(fsr, fsw);
	
	                                        break;
	
	                                    case RC2:
                                            Program.ValidateParams(0x0000000001111111, 0x1011111111110100);
                                            Program.ValidateKeySize(40, 128, 128);
                                            Program.ValidateBlockSize(64);

                                            if (_without_iv)
                                                _blocksize = 0;

                                            else Program.ValidateIntrinsicPadding();

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
	                                        Program.Rc2Crypt(fsr, fsw);
	                                        Program.ClearSymmetricKey();
	                                        break;
	
	                                    case DES:
                                            Program.ValidateParams(0x0000000001111111, 0x1011111111110100);
                                            Program.ValidateKeySize(64);
                                            Program.ValidateBlockSize(64);

                                            if (_without_iv)
                                                _blocksize = 0;

                                            else Program.ValidateIntrinsicPadding();
                                            
                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
	                                        Program.DesCrypt(fsr, fsw);
	                                        Program.ClearSymmetricKey();
	                                        break;
	
	                                    case TDES:
                                            Program.ValidateParams(0x0000000001111111, 0x1011111111110100);

                                            if (_keysize == -1)
                                                _keysize = 192;

                                            else if (_keysize != 128 && _keysize != 192)
                                                throw new Exception(MSG_INVALID_KEY_SIZE);

                                            Program.ValidateBlockSize(64);

                                            if (_without_iv)
                                                _blocksize = 0;

                                            else Program.ValidateIntrinsicPadding();

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
	                                        Program.TripleDesCrypt(fsr, fsw);
	                                        Program.ClearSymmetricKey();
	                                        break;
	
	                                    case RIJNDAEL:
                                            Program.ValidateParams(0x0000000001111111, 0x1011111111110000);

                                            if (_keysize == -1)
                                                _keysize = 256;

                                            else Program.ValidateSizeFrom128To256(_keysize);

                                            if (_blocksize == -1)
                                                _blocksize = 256;

                                            else switch (_blocksize)
                                            {
                                                case 128:
                                                case 160:
                                                case 192:
                                                case 224:
                                                case 256:
                                                    break;

                                                default:
                                                    throw new Exception(MSG_INVALID_BLOCK_SIZE);
                                            }

                                            naux = _blocksize;

                                            if (_without_iv)
                                            {
                                                Program.ValidateParams(0, 0x100);
                                                _blocksize = 0;
                                            }

                                            else
                                            {
                                                Program.ValidateIntrinsicPadding();

                                                if (_feedbacksize == -1)
                                                    _feedbacksize = 128;

                                                else if (_feedbacksize > _blocksize || _feedbacksize % 8 != 0)
                                                    throw new Exception(MSG_INVALID_FEEDBACK_SIZE);
                                            }

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            _blocksize = naux;

	                                        Program.RijndaelCrypt(fsr, fsw);
	                                        Program.ClearSymmetricKey();
	                                        break;
	
	                                    case AES:        
                                            Program.ValidateParams(0x0000000001111111, 0x1011111111110100);
                                            Program.ValidateBlockSize(128);
                                            Program.ValidateFeedbackSize(128);

                                            if (_keysize == -1)
                                                _keysize = 256;

                                            else Program.ValidateSizeFrom128To256(_keysize);

                                            if (_without_iv)
                                            {
                                                if (_ciphermode != CipherMode.CBC)
                                                    throw new Exception(MSG_INVALID_CIPHER_MODE);

                                                _blocksize = 0;
                                            }

                                            else
                                            {
                                                Program.ValidateIntrinsicPadding();

                                                if (_ciphermode == CipherMode.OFB || _ciphermode == CipherMode.CFB)
                                                    throw new Exception(MSG_INVALID_CIPHER_MODE);
                                            }

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.AesCrypt(fsr, fsw);
	                                        Program.ClearSymmetricKey();
		                                    break;
	
	                                    case MARS:
                                            Program.ValidateParams(0x0000000001111111, 0x1111111111110100);

                                            if (_padding != CryptPadding.PKCS7)
                                                throw new Exception(MSG_INVALID_PADDING_MODE);

                                            Program.ValidateKeySize(128, 448, 256);
                                            Program.ValidateBlockSize(128);
                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
	                                        Program.MarsCrypt(fsr, fsw);
	                                        Program.ClearSymmetricKey();
                                            break;

                                        case THREEFISH:
                                            Program.ValidateParams(0x0000000001111111, 0x1011111111110100);

                                            if (_keysize == -1)
                                                _keysize = 256;

                                            else Program.ValidateSizeFrom256to1024
                                            (
                                                  _keysize
                                                , MSG_INVALID_KEY_SIZE
                                            );

                                            if (_blocksize != -1 && _blocksize != _keysize)
                                                throw new Exception(MSG_INVALID_BLOCK_SIZE);

                                            _blocksize = (short)(_without_iv ? 0 : 128);
                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.ThreefishCrypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
                                            break;

                                        case HC:
                                            Program.ValidateParams(0x0000000001111111, 0x1111111111110100);

                                            if (_blocksize == -1)
                                                _blocksize = 128;

                                            if (_keysize == -1)
                                                _keysize = 256;

                                            else switch (_keysize)
                                            {
                                                case 128:
                                                    if (_blocksize != 128)
                                                        throw new Exception(MSG_INVALID_BLOCK_SIZE);

                                                    break;

                                                case 256:
                                                    if (_blocksize != 128 && _blocksize != 256)
                                                        throw new Exception(MSG_INVALID_BLOCK_SIZE);

                                                    break;

                                                default:
                                                    throw new Exception(MSG_INVALID_KEY_SIZE);
                                            }

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.HongjunCrypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
                                            break;

                                        case XSALSA20:
                                            Program.ValidateParams(0x0000000001111111, 0x1111111111110100);
                                            baux = true;
                                            goto case SALSA20;

                                        case CHACHA:
                                            caux = true;
                                            goto case SALSA20;

                                        case SALSA20:
                                            Program.ValidateParams(0x0000000001101111, 0x1111111111110100);

                                            if (_keysize == -1)
                                                _keysize = 256;

                                            else switch (_keysize)
                                            {
                                                case 128:
                                                    if (baux)
                                                        goto default;

                                                    break;

                                                case 256:
                                                    break;

                                                default:
                                                    throw new Exception(MSG_INVALID_KEY_SIZE);
                                            }

                                            Program.ValidateBlockSize(0);
                                            _blocksize = (short)(baux ? 192 : 64);

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l, true);

                                            if (baux) Program.XSalsa20Crypt
                                            (
                                                  _cop == CryptOperation.ENCRYPT
                                                , fsr
                                                , fsw
                                            );

                                            else if (caux) Program.ChaChaCrypt
                                            (
                                                  _cop == CryptOperation.ENCRYPT
                                                , fsr
                                                , fsw
                                            );

                                            else Program.Salsa20Crypt
                                            (
                                                  _cop == CryptOperation.ENCRYPT
                                                , fsr
                                                , fsw
                                            );

                                            Program.ClearSymmetricKey();
                                            break;
	
	                                    case VMPC:
                                            Program.ValidateParams(0x0000000000111111, 0x1111111111110100);
                                            Program.ValidateKeySize(8, 6144, 256);
                                            Program.ValidateBlockSize(8, 6144, 256);
                                            Program.ProvideKey(_overwrite ? ifn : ofn, l, true);
	                                        Program.VmpcCrypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
	                                        Program.ClearSymmetricKey();
	                                        break;

                                        case ISAAC:
                                            _without_iv = true;
                                            Program.ValidateParams(0x0000001001111111, 0x1011111111110100);
                                            Program.ValidateKeySize(32, 8192, 256);
                                            Program.ValidateBlockSize(0);
                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.IsaacCrypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
                                            break;

                                        case RC4:
                                            _without_iv = true;
                                            Program.ValidateParams(0x0000001001111111, 0x1011111111110100);
                                            Program.ValidateKeySize(40, 2048, 256);
                                            Program.ValidateBlockSize(0);
                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.RC4Crypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
                                            break;
	
	                                    case CAMELLIA:
                                            Program.ValidateParams(0x0000001001111111, 0x1011111111110100);

	                                        if (_keysize == -1)
	                                            _keysize = 256;

                                            else Program.ValidateSizeFrom128To256(_keysize);

                                            Program.ValidateBlockSize(128);
                                            
                                            _blocksize  = 0;
                                            _without_iv = true;

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
	                                        Program.CamelliaCrypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
	                                        break;

                                        case SERPENT:
                                            Program.ValidateParams(0x0000001001111111, 0x1011111111110100);

                                            if (_keysize == -1)
                                                _keysize = 256;

                                            else Program.ValidateSizeFrom128To256(_keysize);

                                            Program.ValidateBlockSize(128);
                                            
                                            _blocksize  = 0;
                                            _without_iv = true;

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.SerpentCrypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
                                            break;

                                        case TNEPRES:
                                            Program.ValidateParams(0x0000001001111111, 0x1011111111110100);

                                            if (_keysize == -1)
                                                _keysize = 256;

                                            else Program.ValidateSizeFrom128To256(_keysize);

                                            Program.ValidateBlockSize(128);
                                           
                                            _blocksize  = 0;
                                            _without_iv = true;

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.TnepresCrypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
                                            break;
	
	                                    case BLOWFISH:
                                            Program.ValidateParams(0x0000001001111111, 0x1011111111110100);
                                            Program.ValidateKeySize(8, 448, 256);
                                            Program.ValidateBlockSize(64);
                                            
                                            _blocksize  = 0;
                                            _without_iv = true;

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.BlowfishCrypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
	                                        break;
	
	                                    case TWOFISH:
                                            Program.ValidateParams(0x0000001001111111, 0x1011111111110100);

	                                        if (_keysize == -1)
	                                            _keysize = 256;

                                            else Program.ValidateSizeFrom128To256(_keysize);

                                            Program.ValidateBlockSize(128);
                                            
                                            _blocksize  = 0;
                                            _without_iv = true;

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.TwofishCrypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
	                                        break;
	
	                                    case CAST5:
                                            Program.ValidateParams(0x0000001001111111, 0x1011111111110100);
                                            Program.ValidateKeySize(40, 128, 128);
                                            Program.ValidateBlockSize(64);
                                            
                                            _blocksize  = 0;
                                            _without_iv = true;

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.Cast5Crypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
	                                        break;
	
	                                    case CAST6:
                                            Program.ValidateParams(0x0000001001111111, 0x1011111111110100);
                                            Program.ValidateKeySize(40, 256, 256);
                                            Program.ValidateBlockSize(128);
                                            
                                            _blocksize  = 0;
                                            _without_iv = true;

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.Cast6Crypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
	                                        break;
	
	                                    case IDEA:
                                            Program.ValidateParams(0x0000001001111111, 0x1011111111110100);
                                            Program.ValidateKeySize(128);
                                            Program.ValidateBlockSize(64);
                                            
                                            _blocksize  = 0;
                                            _without_iv = true;
                                            
                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.IdeaCrypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
	                                        break;
	
	                                    case NOEKEON:
                                            Program.ValidateParams(0x0000001001111111, 0x1011111111110100);
                                            Program.ValidateKeySize(128);
                                            Program.ValidateBlockSize(128);
                                            
                                            _blocksize  = 0;
                                            _without_iv = true;

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.NoekeonCrypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
	                                        break;
	
	                                    case GOST:
                                            Program.ValidateParams(0x0000000001111111, 0x1011011111110100);
                                            Program.ValidateKeySize(256);
                                            Program.ValidateBlockSize(64);

                                            if ((_blocksize = (short)(_sbox == IV ? 1024 : 0)) > 0 && _without_iv)
                                            {
                                                saux = "gost-box with iv and without-iv-tweak parameters can not be " +
                                                       "used simultaneously!\n\n>You want to use the initial vector?";

                                                if (!Program.Question(saux))
                                                     _without_iv = false;

                                                else _blocksize = 0;
                                            }

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.GostCrypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
	                                        break;
	
	                                    case SEED:
                                            Program.ValidateParams(0x0000001001111111, 0x1011111111110100);
                                            Program.ValidateKeySize(128);
                                            Program.ValidateBlockSize(128);
                                            
                                            _blocksize  = 0;
                                            _without_iv = true;

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.SeedCrypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
	                                        break;
	
	                                    case SKIPJACK:
                                            Program.ValidateParams(0x0000001001111111, 0x1011111111110100);
                                            Program.ValidateKeySize(40, 128, 128);
                                            Program.ValidateBlockSize(64);
                                            
                                            _blocksize  = 0;
                                            _without_iv = true;

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.SkipjackCrypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
	                                        break;
	
	                                    case TEA:
                                            Program.ValidateParams(0x0000001001111111, 0x1011111111110100);
                                            Program.ValidateKeySize(128);
                                            Program.ValidateBlockSize(64);
                                            
                                            _blocksize  = 0;
                                            _without_iv = true;

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.TeaCrypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
	                                        break;
	
	                                    case XTEA:
                                            Program.ValidateParams(0x0000001001111111, 0x1011111111110100);
                                            Program.ValidateKeySize(128);
                                            Program.ValidateBlockSize(64);
                                            
                                            _blocksize  = 0;
                                            _without_iv = true;

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.XTeaCrypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
	                                        break;
	
	                                    case RC5:
                                            Program.ValidateParams(0x0000001001001111, 0x1011111111110100);
                                            Program.ValidateKeySize(40, (short)(_rc5b64 ? 256 : 128), 128);
                                            Program.ValidateBlockSize((short)(_rc5b64 ? 128 : 64));
                                            
                                            _blocksize  = 0;
                                            _without_iv = true;

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.RC5Crypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
	                                        break;
	
	                                    case RC6:
                                            Program.ValidateParams(0x0000001001111111, 0x1011111111110100);
                                            Program.ValidateKeySize(40, 256, 256);
                                            Program.ValidateBlockSize(128);
                                            
                                            _blocksize  = 0;
                                            _without_iv = true;

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l);
                                            Program.RC6Crypt(_cop == CryptOperation.ENCRYPT, fsr, fsw);
                                            Program.ClearSymmetricKey();
	                                        break;

                                        case DLIES:
                                            if (_generator && _cop == CryptOperation.ENCRYPT) throw new Exception
                                            (
                                                "The key pair generator can not be used simultaneously " +
                                                "with the encryption indicator for DLIES mode!"
                                            );
       
                                            Program.ValidateParams(0x0000000011111111, 0x1110111111100100);
                                            goto case ECIES;

                                        case ECIES:
                                            Program.ValidateParams(0x0000000011111111, 0x1100111111100100);

                                            switch (_ies_cipher)
                                            {
                                                case RIJNDAEL:
                                                    baux = true;

                                                    if (_blocksize == -1)
                                                        _blocksize = 256;

                                                    else switch (_blocksize)
                                                    {
                                                        case 128:
                                                        case 160:
                                                        case 192:
                                                        case 224:
                                                        case 256:
                                                            break;

                                                        default:
                                                            throw new Exception(MSG_INVALID_BLOCK_SIZE);
                                                    }

                                                    goto case TWOFISH;

                                                case AES:
                                                    if (_ciphermode != CipherMode.CBC)
                                                        throw new Exception(MSG_INVALID_CIPHER_MODE);

                                                    goto case TWOFISH;

                                                case SERPENT:
                                                case CAMELLIA:
                                                case TNEPRES:
                                                case TWOFISH:
                                                    if (!baux)
                                                        Program.ValidateBlockSize(128);

                                                    if (_keysize == -1)
                                                        _keysize = 256;

                                                    else Program.ValidateSizeFrom128To256(_keysize);
                                                    break;

                                                case GOST:
                                                    Program.ValidateSizes(256, 64);
                                                    break;

                                                case DES:
                                                    Program.ValidateSizes(64, 64);
                                                    break;

                                                case TDES:
                                                    Program.ValidateSizes(64, 0);

                                                    if (_keysize == -1)
                                                        _keysize = 192;

                                                    else if (_keysize != 128 && _keysize != 192)
                                                        throw new Exception(MSG_INVALID_KEY_SIZE);

                                                    break;

                                                case RC5:
                                                    if (!_rc5b64)
                                                        goto case SKIPJACK;

                                                    Program.ValidateKeySize(40, 256, 256);
                                                    Program.ValidateSizes(128, 0);
                                                    break;

                                                case RC2:
                                                case SKIPJACK:
                                                    Program.ValidateKeySize(40, 128, 128);
                                                    Program.ValidateSizes(64, 0);
                                                    break;

                                                case BLOWFISH:
                                                    Program.ValidateKeySize(40, 448, 256);
                                                    Program.ValidateSizes(64, 0);
                                                    break;

                                                case CAST5:
                                                    Program.ValidateKeySize(40, 128, 128);
                                                    Program.ValidateSizes(64, 0);
                                                    break;

                                                case CAST6:
                                                case RC6:
                                                    Program.ValidateKeySize(40, 256, 256);
                                                    Program.ValidateSizes(128, 0);
                                                    break;
                                                
                                                case SEED:
                                                case NOEKEON:
                                                    Program.ValidateSizes(128, 128);
                                                    break;

                                                case TEA:
                                                case XTEA:
                                                case IDEA:
                                                    Program.ValidateSizes(128, 64);
                                                    break;

                                                case THREEFISH:
	                                                if (_keysize == -1)
	                                                    _keysize = 256;

                                                    else Program.ValidateSizeFrom256to1024
                                                    (
                                                          _keysize
                                                        , MSG_INVALID_KEY_SIZE
                                                    );

                                                    if (_blocksize != -1 && _blocksize != _keysize)
                                                        throw new Exception(MSG_INVALID_BLOCK_SIZE);

                                                    break;

                                                default:
                                                    if (!string.IsNullOrEmpty(_ies_cipher))
                                                        throw new Exception(MSG_INVALID_IES_CIPHER);

                                                    caux = true;
                                                    break;
                                            }

                                            if (_generator)
                                            {
                                                Program.EciesKeyPairGen();
                                                _generator = false;
                                            }

                                            IDigest d   = Program.GetBouncyCastleDigest();
                                            naux        = _blocksize;
                                            _blocksize  = (short)(d.GetDigestSize() * 8);

                                            if (caux)
                                                _keysize = _blocksize;

                                            Program.ProvideKey(_overwrite ? ifn : ofn, l, true);
                                            _blocksize = naux;

                                            Program.IesCrypt(_cop == CryptOperation.ENCRYPT, mode, d, fsr, fsw);
                                            Program.ClearSymmetricKey();
                                            break;

	                                    case RSA:
                                            Program.ValidateParams(0x0110101111111111, 0x0111101100000111);
	                                        baux = true;

                                            if (_rsa_bc && !daux)
                                                _padding = CryptPadding.PKCS1;

                                            else if (!_rsa_bc && Type.GetType("Mono.Runtime") == null) 
	                                        {
	                                            OperatingSystem os = Environment.OSVersion;
	                                            switch (os.Platform)
		                                        {
		                                            case PlatformID.Win32S:
		                                            case PlatformID.Win32Windows:
		                                            case PlatformID.Win32NT:
                                                        baux = os.Version.Major > 5 || (os.Version.Major > 4 && os.Version.Minor > 0);
		                                                break;
		                                        }
		                                    }

                                            if (!baux && _padding == CryptPadding.OAEP)
	                                            throw new Exception("Microsoft CryptoAPI only supports OAEP since Windows XP!");

                                            if (!string.IsNullOrEmpty(_cerfile))
                                            {
                                                if (_generator)
                                                {
                                                    _generator = false;
                                                    Messenger.Print
                                                    (
                                                          Messenger.Icon.WARNING
                                                        , MSG_GEN_INCOMPATIBLE
                                                        , false
                                                        , true
                                                    );
                                                }

                                                Program.RsaCrypt
                                                (
                                                      Program.GetRsaFromCertificateFile(_cop)
                                                    , fsr
                                                    , fsw
                                                    , true
                                                );
                                            }

                                            else if (!string.IsNullOrEmpty(_cerstore))
                                            {
                                                if (_generator)
                                                {
                                                    _generator = false;
                                                    Messenger.Print
                                                    (
                                                          Messenger.Icon.WARNING
                                                        , MSG_GEN_INCOMPATIBLE
                                                        , false
                                                        , true
                                                    );
                                                }

                                                Program.RsaCrypt
                                                (
                                                      Program.GetRsaFromCertificateStore()
                                                    , fsr
                                                    , fsw
                                                    , true
                                                );
                                            }
                                            else
                                            {
                                                Program.RsaValidateKeySize();
                                                using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(_keysize))
                                                {
                                                    if (_cop == CryptOperation.ENCRYPT)
                                                    {
                                                        if (_generator)
                                                        {
                                                            if (_crossbreeding)
                                                            {
                                                                _crossbreeding = false;
                                                                Messenger.Print
                                                                (
                                                                      Messenger.Icon.WARNING
                                                                    , MSG_CROSS_INCOMPATIBLE
                                                                    , false
                                                                    , true
                                                                );
                                                            }

                                                            Program.RsaKeyPairGen(rsa);
                                                            _generator = false;
                                                        }

                                                        else
                                                        {
                                                            if (!File.Exists(_public_key))
                                                                throw new Exception(MSG_INVALID_PUBLIC_KEY);

                                                            if (!_crossbreeding)
                                                                Program.RsaImportKey(rsa, _public_key);

                                                            else Program.PgpPublicKeyToRsa
                                                            (
                                                                  Program.GetPgpPublicKey()
                                                                , rsa
                                                            );
                                                        }
                                                    }

                                                    else if (_cop == CryptOperation.DECRYPT)
                                                    {
                                                        if (!File.Exists(_private_key))
                                                            throw new Exception(MSG_INVALID_PRIVATE_KEY);

                                                        if (!_crossbreeding)
                                                            Program.RsaImportKey(rsa, _private_key);

                                                        else Program.PgpPrivateKeyToRsa
                                                        (
                                                              Program.GetPgpPrivateKey()
                                                            , rsa
                                                        );
                                                    }

                                                    Program.RsaCrypt(rsa, fsr, fsw);
                                                }
                                            }
	
		                                    break;
	
	                                    case PGP:                                                 
                                            Program.ValidateParams(0x1111101101111111, 0x0101100010000111);

                                            if (!string.IsNullOrEmpty(_cerstore))
                                            {
                                                if (_pgp_algorithm != RSA)
                                                {
                                                    _pgp_algorithm = RSA;
                                                    Messenger.Print
                                                    (
                                                          Messenger.Icon.WARNING
                                                        , MSG_CER_ALG_INCOMPATIBLE
                                                        , false
                                                        , true
                                                    );
                                                }

                                                if (_generator)
                                                {
                                                    _generator = false;
                                                    Messenger.Print
                                                    (
                                                          Messenger.Icon.WARNING
                                                        , MSG_GEN_INCOMPATIBLE
                                                        , false
                                                        , true
                                                    );
                                                }

                                                if (_pgp_sign)
                                                {
                                                    if (_cop == CryptOperation.DECRYPT)
                                                    {
                                                        _pgp_sign = false;
                                                        Messenger.Print
                                                        (
                                                              Messenger.Icon.WARNING
                                                            , MSG_PGP_SIGN_USE
                                                            , false
                                                            , true
                                                        );
                                                    }

                                                    else
                                                    {
                                                        if (string.IsNullOrEmpty(_cerfile))
                                                            throw new Exception(MSG_INVALID_PRIVATE_KEY);

                                                        using (RSACryptoServiceProvider rsa = Program.GetRsaFromCertificateFile(CryptOperation.DECRYPT))
                                                            _pgp_pvk = Program.GetPgpPrivateKeyFromRsa(rsa);
                                                    }
                                                }

                                                using (RSACryptoServiceProvider rsa = Program.GetRsaFromCertificateStore())
                                                {
                                                    if (_cop == CryptOperation.ENCRYPT) Program.PgpEncrypt
                                                    (
                                                          Program.GetPgpPublicKeyFromRsa(rsa)
                                                        , fsr
                                                        , fsw
                                                        , Path.GetFileName(fsw.Name)
                                                        , _format == CryptFormat.ARMORED
                                                        , true
                                                    );

                                                    else Program.PgpDecrypt
                                                    (
                                                          Program.GetPgpPrivateKeyFromRsa(rsa)
                                                        , fsr
                                                        , fsw
                                                    );
                                                }
                                            }

	                                        else if (!string.IsNullOrEmpty(_cerfile))
	                                        {
                                                if (_pgp_algorithm != RSA)
                                                {
                                                    _pgp_algorithm = RSA;
                                                    Messenger.Print
                                                    (
                                                          Messenger.Icon.WARNING
                                                        , MSG_CER_ALG_INCOMPATIBLE
                                                        , false
                                                        , true
                                                    );
                                                }

                                                if (_generator)
                                                {
                                                    _generator = false;
                                                    Messenger.Print
                                                    (
                                                          Messenger.Icon.WARNING
                                                        , MSG_GEN_INCOMPATIBLE
                                                        , false
                                                        , true
                                                    );
                                                }

                                                if (_pgp_sign)
                                                {
                                                    if (_cop == CryptOperation.DECRYPT)
                                                    {
                                                        _pgp_sign = false;
                                                        Messenger.Print
                                                        (
                                                              Messenger.Icon.WARNING
                                                            , MSG_PGP_SIGN_USE
                                                            , false
                                                            , true
                                                        );
                                                    }

                                                    else
                                                    {
                                                        if ((baux = !string.IsNullOrEmpty(_cer_pgp_pvk)))
                                                        {
                                                            saux     = _cerfile;
                                                            _cerfile = _cer_pgp_pvk;
                                                        }

                                                        using (RSACryptoServiceProvider rsa = Program.GetRsaFromCertificateFile(CryptOperation.DECRYPT))
                                                            _pgp_pvk = Program.GetPgpPrivateKeyFromRsa(rsa);

                                                        if (baux)
                                                            _cerfile = saux;
                                                    }
                                                }

	                                            using (RSACryptoServiceProvider rsa = Program.GetRsaFromCertificateFile(_cop))
	                                            {
                                                    if (_cop == CryptOperation.ENCRYPT)
                                                    {
                                                        Program.PgpEncrypt
                                                        (
                                                              Program.GetPgpPublicKeyFromRsa(rsa)
                                                            , fsr
                                                            , fsw
                                                            , Path.GetFileName(fsw.Name)
                                                            , _format == CryptFormat.ARMORED
                                                            , true
                                                        );
                                                    }

                                                    else Program.PgpDecrypt
                                                    (
                                                          Program.GetPgpPrivateKeyFromRsa(rsa)
                                                        , fsr
                                                        , fsw
                                                    );
	                                            }
	                                        }
	
	                                        else
	                                        {
	                                            if (_cop == CryptOperation.ENCRYPT)
	                                            {
                                                    if (_generator)
	                                                {
                                                        if (_crossbreeding)
                                                        {
                                                            _crossbreeding = false;
                                                            Messenger.Print
                                                            (
                                                                  Messenger.Icon.WARNING
                                                                , MSG_CROSS_INCOMPATIBLE
                                                                , false
                                                                , true
                                                            );
                                                        }

                                                        if (_pgp_algorithm == RSA)
                                                            Program.PgpRsaKeyPairGen(_format == CryptFormat.ARMORED);

                                                        else if (_pgp_algorithm == ELGAMAL) 
                                                            Program.PgpElGamalKeyPairGen(_format == CryptFormat.ARMORED);

                                                        else throw new Exception(MSG_INVALID_PGP_ALGORITHM);

                                                        _generator = false;
	                                                    ppbk       = Program.GetPgpPublicKey();

                                                        if (_pgp_sign)
                                                            _pgp_pvk = Program.GetPgpPrivateKey(true);
	                                                }
	
	                                                else
	                                                {
                                                        if (!File.Exists(_public_key))
	                                                        throw new Exception(MSG_INVALID_PUBLIC_KEY);

                                                        if (!_crossbreeding)
                                                        {
                                                            if (_pgp_sign)
                                                            {
                                                                if (!File.Exists(_private_key))
                                                                    throw new Exception(MSG_INVALID_PRIVATE_KEY);

                                                                _pgp_pvk = Program.GetPgpPrivateKey(true);
                                                            }

                                                            ppbk = Program.GetPgpPublicKey();
                                                        }

                                                        else switch (_pgp_algorithm)
                                                        {
                                                            case RSA:
                                                                using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                                                                {
                                                                    _format = CryptFormat.UNKNOWN;

                                                                    if (!_pgp_sign)
                                                                        Program.RsaImportKey(rsa, _public_key);

                                                                    else
                                                                    {
                                                                        if (!File.Exists(_private_key))
                                                                            throw new Exception(MSG_INVALID_PRIVATE_KEY);

                                                                        Program.RsaImportKey(rsa, _private_key);
                                                                        _pgp_pvk = Program.GetPgpPrivateKeyFromRsa(rsa);
                                                                    }

                                                                    ppbk = Program.GetPgpPublicKeyFromRsa(rsa);
                                                                }
                                                                break;

                                                            case ELGAMAL:
                                                                if (_pgp_sign) throw new Exception
                                                                (
                                                                    "Elgamal keys can not be used to sign with Pgp, an Dsa " +
                                                                    "private key is needed! You can try export keys from "   + 
                                                                    "Elgamal to Pgp."
                                                                );

                                                                ppbk = Program.ElGamalToPgpPublicKey
                                                                (
                                                                    epbk = (ElGamalPublicKeyParameters)Program.ElGamalImportKey
                                                                    (
                                                                        _public_key
                                                                    )
                                                                );

                                                                break;
                                                            default:
                                                                throw new Exception(MSG_INVALID_PGP_ALGORITHM);
                                                        }
	                                                }

	                                                Program.PgpEncrypt
	                                                (
	                                                      ppbk
	                                                    , fsr
	                                                    , fsw
	                                                    , Path.GetFileName(fsw.Name)
                                                        , _format == CryptFormat.ARMORED
	                                                    , true
	                                                );
	                                            }
	
	                                            else
	                                            {
                                                    if (_pgp_sign)
                                                    {
                                                        _pgp_sign = false;
                                                        Messenger.Print
                                                        (
                                                              Messenger.Icon.WARNING
                                                            , MSG_PGP_SIGN_USE
                                                            , false
                                                            , true
                                                        );
                                                    }

                                                    if (!File.Exists(_private_key))
	                                                    throw new Exception(MSG_INVALID_PRIVATE_KEY);

                                                    if (!_crossbreeding)
                                                        _pgp_pvk = Program.GetPgpPrivateKey();

                                                    else switch (_pgp_algorithm)
                                                    {
                                                        case RSA:
                                                            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                                                            {
                                                                _format = CryptFormat.UNKNOWN;
                                                                Program.RsaImportKey(rsa, _private_key);
                                                                _pgp_pvk = Program.GetPgpPrivateKeyFromRsa(rsa);
                                                            }
                                                            break;

                                                        case ELGAMAL:
                                                            if (!File.Exists(_public_key))
                                                                throw new Exception(MSG_INVALID_PUBLIC_KEY);

                                                            _pgp_pvk = Program.ElGamalToPgpPrivateKey
                                                            (
                                                                  (ElGamalPublicKeyParameters)Program.ElGamalImportKey(_public_key)
                                                                , (ElGamalPrivateKeyParameters)Program.ElGamalImportKey(_private_key)
                                                            );
                                                            break;

                                                        default:
                                                            throw new Exception(MSG_INVALID_PGP_ALGORITHM);
                                                    }

                                                    Program.PgpDecrypt(_pgp_pvk, fsr, fsw);
	                                            }
	                                        }
	
	                                        break;
	
	                                    case ELGAMAL:
                                            Program.ValidateParams(0x0110101111111111, 0x1111101111100111);

                                            if (!daux)
	                                            _padding = CryptPadding.PKCS1;
	
	                                        if (_keysize == -1)
	                                            _keysize = 768;
	
	                                        ElGamalKeyParameters ekp = null;
	
	                                        if (_cop == CryptOperation.ENCRYPT)
	                                        {
                                                if (_generator)
                                                {
                                                    if (_crossbreeding)
                                                    {
                                                        _crossbreeding = false;
                                                        Messenger.Print
                                                        (
                                                              Messenger.Icon.WARNING
                                                            , MSG_CROSS_INCOMPATIBLE
                                                            , false
                                                            , true
                                                        );
                                                    }

                                                    Program.ElGamalKeyPairGen();
                                                    _generator = false;
                                                }

                                                else if (!File.Exists(_public_key))
                                                    throw new Exception(MSG_INVALID_PUBLIC_KEY);

                                                if (_crossbreeding)
                                                     ekp = Program.PgpPublicKeyToElGamal(Program.GetPgpPublicKey());

                                                else ekp = Program.ElGamalImportKey(_public_key);
	                                        }
	
	                                        else if (_cop == CryptOperation.DECRYPT)
	                                        {
                                                if (!File.Exists(_private_key))
	                                                throw new Exception(MSG_INVALID_PRIVATE_KEY);

                                                if (_crossbreeding)
                                                     ekp = Program.PgpPrivateKeyToElGamal(Program.GetPgpPrivateKey());

                                                else ekp = Program.ElGamalImportKey(_private_key);
	                                        }
	
	                                        Program.ElGamalCrypt(_cop == CryptOperation.ENCRYPT, ekp, fsr, fsw);
	                                        break;

                                        case NACCACHE:
                                            Program.ValidateParams(0x1111111111111111, 0x1111111111100111);

                                            if (_keysize == -1)
                                                _keysize = 768;

                                            NaccacheSternKeyParameters nsk = null;

                                            if (_cop == CryptOperation.ENCRYPT)
                                            {
                                                if (_generator)
                                                {
                                                    Program.NaccacheSternKeyPairGen();
                                                    _generator = false;
                                                }

                                                else if (!File.Exists(_public_key))
                                                    throw new Exception(MSG_INVALID_PUBLIC_KEY);

                                                nsk = Program.NaccacheSternImportKey(_public_key);
                                            }

                                            else if (_cop == CryptOperation.DECRYPT)
                                            {
                                                if (!File.Exists(_private_key))
                                                    throw new Exception(MSG_INVALID_PRIVATE_KEY);

                                                nsk = Program.NaccacheSternImportKey(_private_key);
                                            }

                                            Program.NaccacheSternCrypt
                                            (
                                                  _cop == CryptOperation.ENCRYPT
                                                , nsk
                                                , fsr
                                                , fsw
                                            );

                                            break;
	
		                                default:
		                                    throw new Exception("Invalid mode!");
		                            }
		                        }
							}

                            if (_without_iv)
                                _blocksize = naux;

                            if (_overwrite)
	                            Program.MoveFile(ofn, ifn);
	
	                        else if (l > 1) Messenger.Print
	                        (
	                              Messenger.Icon.INFORMATION
	                            , string.Format
	                              (
	                                    "Process completed with the file \"{0}\" in \"{1}\""
	                                  , Path.GetFileName(ofn)
	                                  , Path.GetDirectoryName(ofn)
	                              )
	                            , false
	                            , true
	                        );

                            _e_num = 0;
						}

                        catch (Exception e)
                        {
                            if (_percent < 100)
                                Program.Progress(1, 1, 0);

                            if (!_overwrite && File.Exists(ofn))
                                File.Delete(ofn);

                            switch (iaux = Marshal.GetHRForException(e))
                            {
                                case -2146233088:
                                    if (mode != RSA && mode != ELGAMAL)
                                        if (e.Message.Contains("pad block corrupted"))
                                            goto case -2146893819;

                                    break;

                                case -2146233296:
                                case -2146893819:
                                    if (_haspwd)
                                    {
                                        if (_raisepwd) 
                                            e = new Exception(MSG_INCORRECT_PWD_SALT + '!');

                                        else
                                        {
                                            Messenger.Print
                                            (
                                                  Messenger.Icon.ERROR
                                                  , MSG_INCORRECT_PWD_SALT + 
                                                  (l < 2 ? "! " : " for the file \""  +
                                                  (_overwrite ? ifn : ofn) + "\". ") +
                                                  MSG_PLEASE_TRY_AGAIN
                                                , false
                                                , true
                                            );

                                            Program.ExceptionControl(iaux);

                                            _password    = string.Empty;
                                            _salt        = string.Empty;
                                            _saltleaking = false;

                                            if (_without_iv)
                                                _blocksize = naux;

                                            --i;
                                            continue;
                                        }
                                    }

                                    break;
                            }

                            if (_raise)
                                throw e;

                            Messenger.Print
                            (
                                  Messenger.Icon.ERROR
                                , "An exception occurred while processing the file: \"" +
                                  Path.GetFileName(_overwrite ? ifn : ofn) + "\". " +
                                  e.Message
                                , false
                                , true
                            );

                            Program.ExceptionControl(iaux);
                        }
					}
					
					Messenger.Print(Messenger.Icon.INFORMATION, MSG_DONE);
                }

                catch (Exception e)
                {
                    Program.ShowBanner();

                    if (_percent < 100)
                        Program.Progress(1, 1, 0);

                    if (!string.IsNullOrEmpty(e.Message))
                    {
                        Messenger.Print(Messenger.Icon.ERROR, e.Message);
                        Console.WriteLine();
                    }

                    Environment.Exit(1);
                }
            }
        }
    }
}
